Compare commits

...

2 Commits

Author SHA1 Message Date
65a8f1e6c3 🐛 Bug fixes on config refactor 2024-12-21 01:58:49 +08:00
2671ffad4b Allow setting image preview quality 2024-12-21 01:47:52 +08:00
18 changed files with 191 additions and 85 deletions

3
.fvmrc
View File

@ -1,3 +0,0 @@
{
"flutter": "stable"
}

View File

@ -1,16 +0,0 @@
# surface
A new Flutter project.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.

View File

@ -190,6 +190,13 @@
"settingsNetworkServerPreset": "Present HyperNet Server", "settingsNetworkServerPreset": "Present HyperNet Server",
"settingsNetworkServerPresetDescription": "You can choose one of our preset HyperNet server addresses from the list on the right.", "settingsNetworkServerPresetDescription": "You can choose one of our preset HyperNet server addresses from the list on the right.",
"settingsNetworkServerSaved": "Server address saved.", "settingsNetworkServerSaved": "Server address saved.",
"settingsPerformance": "Performance",
"settingsImageQuality": "Image Quality",
"settingsImageQualityDescription": "Set the image quality, it will affect the decoding speed of the image.",
"settingsImageQualityLowest": "Lowest",
"settingsImageQualityLow": "Low",
"settingsImageQualityMedium": "Medium",
"settingsImageQualityHigh": "High",
"settingsMisc": "Misc", "settingsMisc": "Misc",
"settingsMiscAbout": "About", "settingsMiscAbout": "About",
"settingsMiscAboutDescription": "View the version information of Solian.", "settingsMiscAboutDescription": "View the version information of Solian.",

View File

@ -188,6 +188,13 @@
"settingsNetworkServerPreset": "预设的 HyperNet 服务器", "settingsNetworkServerPreset": "预设的 HyperNet 服务器",
"settingsNetworkServerPresetDescription": "你可以在旁边的列表中选择我们提供的预设 HyperNet 服务器地址。", "settingsNetworkServerPresetDescription": "你可以在旁边的列表中选择我们提供的预设 HyperNet 服务器地址。",
"settingsNetworkServerSaved": "服务器地址已保存。", "settingsNetworkServerSaved": "服务器地址已保存。",
"settingsPerformance": "性能",
"settingsImageQuality": "图片预览质量",
"settingsImageQualityDescription": "设置图片预览质量,会影响图片解码速度。",
"settingsImageQualityLowest": "极低",
"settingsImageQualityLow": "低",
"settingsImageQualityMedium": "中",
"settingsImageQualityHigh": "高",
"settingsMisc": "杂项", "settingsMisc": "杂项",
"settingsMiscAbout": "关于", "settingsMiscAbout": "关于",
"settingsMiscAboutDescription": "查看 Solian 的版本信息。", "settingsMiscAboutDescription": "查看 Solian 的版本信息。",

View File

@ -188,6 +188,13 @@
"settingsNetworkServerPreset": "預設的 HyperNet 服務器", "settingsNetworkServerPreset": "預設的 HyperNet 服務器",
"settingsNetworkServerPresetDescription": "你可以在旁邊的列表中選擇我們提供的預設 HyperNet 服務器地址。", "settingsNetworkServerPresetDescription": "你可以在旁邊的列表中選擇我們提供的預設 HyperNet 服務器地址。",
"settingsNetworkServerSaved": "服務器地址已保存。", "settingsNetworkServerSaved": "服務器地址已保存。",
"settingsPerformance": "性能",
"settingsImageQuality": "圖片預覽質量",
"settingsImageQualityDescription": "設置圖片預覽質量,會影響圖片解碼速度。",
"settingsImageQualityLowest": "極低",
"settingsImageQualityLow": "低",
"settingsImageQualityMedium": "中",
"settingsImageQualityHigh": "高",
"settingsMisc": "雜項", "settingsMisc": "雜項",
"settingsMiscAbout": "關於", "settingsMiscAbout": "關於",
"settingsMiscAboutDescription": "查看 Solian 的版本信息。", "settingsMiscAboutDescription": "查看 Solian 的版本信息。",
@ -441,5 +448,10 @@
"postImageShareReadMore": "掃描右側 QRCode 查看全文", "postImageShareReadMore": "掃描右側 QRCode 查看全文",
"postImageShareAds": "來 Solar Network 探索更多有趣帖子", "postImageShareAds": "來 Solar Network 探索更多有趣帖子",
"postShare": "分享", "postShare": "分享",
"postShareImage": "分享帖圖" "postShareImage": "分享帖圖",
"appInitializing": "正在初始化",
"poweredBy": "由 {} 提供支持",
"shareIntent": "分享",
"shareIntentDescription": "您想對您分享的內容做些什麼?",
"shareIntentPostStory": "發佈動態"
} }

View File

@ -188,6 +188,13 @@
"settingsNetworkServerPreset": "預設的 HyperNet 伺服器", "settingsNetworkServerPreset": "預設的 HyperNet 伺服器",
"settingsNetworkServerPresetDescription": "你可以在旁邊的列表中選擇我們提供的預設 HyperNet 伺服器地址。", "settingsNetworkServerPresetDescription": "你可以在旁邊的列表中選擇我們提供的預設 HyperNet 伺服器地址。",
"settingsNetworkServerSaved": "伺服器地址已儲存。", "settingsNetworkServerSaved": "伺服器地址已儲存。",
"settingsPerformance": "效能",
"settingsImageQuality": "圖片預覽質量",
"settingsImageQualityDescription": "設定圖片預覽質量,會影響圖片解碼速度。",
"settingsImageQualityLowest": "極低",
"settingsImageQualityLow": "低",
"settingsImageQualityMedium": "中",
"settingsImageQualityHigh": "高",
"settingsMisc": "雜項", "settingsMisc": "雜項",
"settingsMiscAbout": "關於", "settingsMiscAbout": "關於",
"settingsMiscAboutDescription": "檢視 Solian 的版本資訊。", "settingsMiscAboutDescription": "檢視 Solian 的版本資訊。",
@ -441,5 +448,10 @@
"postImageShareReadMore": "掃描右側 QRCode 檢視全文", "postImageShareReadMore": "掃描右側 QRCode 檢視全文",
"postImageShareAds": "來 Solar Network 探索更多有趣帖子", "postImageShareAds": "來 Solar Network 探索更多有趣帖子",
"postShare": "分享", "postShare": "分享",
"postShareImage": "分享帖圖" "postShareImage": "分享帖圖",
"appInitializing": "正在初始化",
"poweredBy": "由 {} 提供支援",
"shareIntent": "分享",
"shareIntentDescription": "您想對您分享的內容做些什麼?",
"shareIntentPostStory": "釋出動態"
} }

View File

@ -355,7 +355,7 @@ SPEC CHECKSUMS:
flutter_native_splash: e8a1e01082d97a8099d973f919f57904c925008a flutter_native_splash: e8a1e01082d97a8099d973f919f57904c925008a
flutter_udid: a2482c67a61b9c806ef59dd82ed8d007f1b7ac04 flutter_udid: a2482c67a61b9c806ef59dd82ed8d007f1b7ac04
flutter_webrtc: 1a53bd24f97bcfeff512f13699e721897f261563 flutter_webrtc: 1a53bd24f97bcfeff512f13699e721897f261563
gal: 61e868295d28fe67ffa297fae6dacebf56fd53e1 gal: 6a522c75909f1244732d4596d11d6a2f86ff37a5
GoogleAppMeasurement: 987769c4ca6b968f2479fbcc9fe3ce34af454b8e GoogleAppMeasurement: 987769c4ca6b968f2479fbcc9fe3ce34af454b8e
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d

View File

@ -18,6 +18,7 @@ import 'package:styled_widget/styled_widget.dart';
import 'package:surface/firebase_options.dart'; import 'package:surface/firebase_options.dart';
import 'package:surface/providers/channel.dart'; import 'package:surface/providers/channel.dart';
import 'package:surface/providers/chat_call.dart'; import 'package:surface/providers/chat_call.dart';
import 'package:surface/providers/config.dart';
import 'package:surface/providers/link_preview.dart'; import 'package:surface/providers/link_preview.dart';
import 'package:surface/providers/navigation.dart'; import 'package:surface/providers/navigation.dart';
import 'package:surface/providers/notification.dart'; import 'package:surface/providers/notification.dart';
@ -85,13 +86,16 @@ class SolianApp extends StatelessWidget {
assetLoader: JsonAssetLoader(), assetLoader: JsonAssetLoader(),
child: MultiProvider( child: MultiProvider(
providers: [ providers: [
// System extensions layer
Provider(create: (ctx) => HomeWidgetProvider(ctx)),
// Preferences layer
Provider(create: (ctx) => ConfigProvider(ctx)),
// Display layer // Display layer
ChangeNotifierProvider(create: (_) => ThemeProvider()), ChangeNotifierProvider(create: (_) => ThemeProvider()),
ChangeNotifierProvider(create: (ctx) => NavigationProvider()), ChangeNotifierProvider(create: (ctx) => NavigationProvider()),
// System extensions layer
Provider(create: (ctx) => HomeWidgetProvider(ctx)),
// Data layer // Data layer
Provider(create: (ctx) => SnNetworkProvider(ctx)), Provider(create: (ctx) => SnNetworkProvider(ctx)),
Provider(create: (ctx) => UserDirectoryProvider(ctx)), Provider(create: (ctx) => UserDirectoryProvider(ctx)),
@ -162,13 +166,14 @@ class _AppSplashScreen extends StatefulWidget {
class _AppSplashScreenState extends State<_AppSplashScreen> { class _AppSplashScreenState extends State<_AppSplashScreen> {
bool _isReady = false; bool _isReady = false;
late StreamSubscription _shareIntentSubscription;
Future<void> _initialize() async { Future<void> _initialize() async {
try { try {
final home = context.read<HomeWidgetProvider>(); final home = context.read<HomeWidgetProvider>();
await home.initialize(); await home.initialize();
if (!mounted) return; if (!mounted) return;
// The Network initialization must be done after the HomeWidget initialization
// The Network initialization will save the server url to the HomeWidget
// The Network initialization will also save initialize the Config, so it not need to be initialized again
final sn = context.read<SnNetworkProvider>(); final sn = context.read<SnNetworkProvider>();
await sn.initializeUserAgent(); await sn.initializeUserAgent();
if (!mounted) return; if (!mounted) return;

43
lib/providers/config.dart Normal file
View File

@ -0,0 +1,43 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:surface/providers/widget.dart';
const kAtkStoreKey = 'nex_user_atk';
const kRtkStoreKey = 'nex_user_rtk';
const kNetworkServerDefault = 'https://api.sn.solsynth.dev';
const kNetworkServerStoreKey = 'app_server_url';
const Map<String, FilterQuality> kImageQualityLevel = {
'settingsImageQualityLowest': FilterQuality.none,
'settingsImageQualityLow': FilterQuality.low,
'settingsImageQualityMedium': FilterQuality.medium,
'settingsImageQualityHigh': FilterQuality.high,
};
class ConfigProvider {
late final SharedPreferences prefs;
late final HomeWidgetProvider _home;
ConfigProvider(BuildContext context) {
_home = context.read<HomeWidgetProvider>();
}
Future<void> initialize() async {
prefs = await SharedPreferences.getInstance();
}
FilterQuality get imageQuality {
return kImageQualityLevel.values.elementAtOrNull(prefs.getInt('app_image_quality') ?? 3) ?? FilterQuality.high;
}
String get serverUrl {
return prefs.getString(kNetworkServerStoreKey) ?? kNetworkServerDefault;
}
set serverUrl(String url) {
prefs.setString(kNetworkServerStoreKey, url);
_home.saveWidgetData("nex_server_url", url);
}
}

View File

@ -11,15 +11,10 @@ import 'package:package_info_plus/package_info_plus.dart';
import 'package:device_info_plus/device_info_plus.dart'; import 'package:device_info_plus/device_info_plus.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:surface/providers/config.dart';
import 'package:surface/providers/widget.dart'; import 'package:surface/providers/widget.dart';
import 'package:synchronized/synchronized.dart'; import 'package:synchronized/synchronized.dart';
const kAtkStoreKey = 'nex_user_atk';
const kRtkStoreKey = 'nex_user_rtk';
const kNetworkServerDefault = 'https://api.sn.solsynth.dev';
const kNetworkServerStoreKey = 'app_server_url';
const kNetworkServerDirectory = [ const kNetworkServerDirectory = [
('Solar Network', 'https://api.sn.solsynth.dev'), ('Solar Network', 'https://api.sn.solsynth.dev'),
('Local', 'http://localhost:8001'), ('Local', 'http://localhost:8001'),
@ -29,6 +24,7 @@ class SnNetworkProvider {
late final Dio client; late final Dio client;
late final SharedPreferences _prefs; late final SharedPreferences _prefs;
late final ConfigProvider _config;
late final HomeWidgetProvider _home; late final HomeWidgetProvider _home;
String? _userAgent; String? _userAgent;
@ -66,11 +62,12 @@ class SnNetworkProvider {
), ),
); );
SharedPreferences.getInstance().then((prefs) { _config = context.read<ConfigProvider>();
_prefs = prefs; _config.initialize().then((_) {
client.options.baseUrl = _prefs.getString(kNetworkServerStoreKey) ?? kNetworkServerDefault; _prefs = _config.prefs;
client.options.baseUrl = _config.serverUrl;
if (!context.mounted) return; if (!context.mounted) return;
_home.saveWidgetData("server_url", client.options.baseUrl); _home.saveWidgetData("nex_server_url", client.options.baseUrl);
}); });
} }
@ -197,7 +194,7 @@ class SnNetworkProvider {
} }
void setBaseUrl(String url) { void setBaseUrl(String url) {
_config.serverUrl = url;
client.options.baseUrl = url; client.options.baseUrl = url;
_home.saveWidgetData("server_url", client.options.baseUrl);
} }
} }

View File

@ -1,9 +1,10 @@
import 'dart:developer'; import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:home_widget/home_widget.dart'; import 'package:path/path.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:surface/providers/config.dart';
import 'package:surface/providers/sn_network.dart'; import 'package:surface/providers/sn_network.dart';
import 'package:surface/providers/widget.dart'; import 'package:surface/providers/widget.dart';
import 'package:surface/types/account.dart'; import 'package:surface/types/account.dart';
@ -14,10 +15,12 @@ class UserProvider extends ChangeNotifier {
late final SnNetworkProvider _sn; late final SnNetworkProvider _sn;
late final HomeWidgetProvider _home; late final HomeWidgetProvider _home;
late final ConfigProvider _config;
UserProvider(BuildContext context) { UserProvider(BuildContext context) {
_sn = context.read<SnNetworkProvider>(); _sn = context.read<SnNetworkProvider>();
_home = context.read<HomeWidgetProvider>(); _home = context.read<HomeWidgetProvider>();
_config = context.read<ConfigProvider>();
} }
Future<String?> get atk async { Future<String?> get atk async {
@ -26,8 +29,7 @@ class UserProvider extends ChangeNotifier {
} }
Future<void> initialize() async { Future<void> initialize() async {
final prefs = await SharedPreferences.getInstance(); final value = _config.prefs.getString(kAtkStoreKey);
final value = prefs.getString(kAtkStoreKey);
isAuthorized = value != null; isAuthorized = value != null;
notifyListeners(); notifyListeners();
refreshUser().then((value) { refreshUser().then((value) {

View File

@ -1,10 +1,10 @@
import 'dart:io'; import 'dart:io';
import 'package:collection/collection.dart';
import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:material_symbols_icons/symbols.dart'; import 'package:material_symbols_icons/symbols.dart';
@ -12,6 +12,7 @@ import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
import 'package:surface/providers/config.dart';
import 'package:surface/providers/sn_network.dart'; import 'package:surface/providers/sn_network.dart';
import 'package:surface/providers/theme.dart'; import 'package:surface/providers/theme.dart';
import 'package:surface/theme.dart'; import 'package:surface/theme.dart';
@ -25,7 +26,7 @@ class SettingsScreen extends StatefulWidget {
} }
class _SettingsScreenState extends State<SettingsScreen> { class _SettingsScreenState extends State<SettingsScreen> {
SharedPreferences? _prefs; late final SharedPreferences _prefs;
String _docBasepath = '/'; String _docBasepath = '/';
final TextEditingController _serverUrlController = TextEditingController(); final TextEditingController _serverUrlController = TextEditingController();
@ -39,12 +40,9 @@ class _SettingsScreenState extends State<SettingsScreen> {
setState(() {}); setState(() {});
} }
}); });
SharedPreferences.getInstance().then((prefs) { final config = context.read<ConfigProvider>();
setState(() { _prefs = config.prefs;
_prefs = prefs; _serverUrlController.text = config.serverUrl;
_serverUrlController.text = prefs.getString(kNetworkServerStoreKey) ?? kNetworkServerDefault;
});
});
} }
@override @override
@ -60,6 +58,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
return Scaffold( return Scaffold(
body: SingleChildScrollView( body: SingleChildScrollView(
child: Column( child: Column(
spacing: 16,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Column( Column(
@ -78,7 +77,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
if (image == null) return; if (image == null) return;
await File(image.path).copy('$_docBasepath/app_background_image'); await File(image.path).copy('$_docBasepath/app_background_image');
_prefs?.setBool('has_background_image', true); _prefs.setBool('has_background_image', true);
setState(() {}); setState(() {});
}, },
@ -99,29 +98,28 @@ class _SettingsScreenState extends State<SettingsScreen> {
trailing: const Icon(Symbols.chevron_right), trailing: const Icon(Symbols.chevron_right),
onTap: () { onTap: () {
File('$_docBasepath/app_background_image').deleteSync(); File('$_docBasepath/app_background_image').deleteSync();
_prefs?.remove('has_background_image'); _prefs.remove('has_background_image');
setState(() {}); setState(() {});
}, },
); );
}), }),
if (_prefs != null) CheckboxListTile(
CheckboxListTile( title: Text('settingsThemeMaterial3').tr(),
title: Text('settingsThemeMaterial3').tr(), subtitle: Text('settingsThemeMaterial3Description').tr(),
subtitle: Text('settingsThemeMaterial3Description').tr(), contentPadding: const EdgeInsets.only(left: 24, right: 17),
contentPadding: const EdgeInsets.only(left: 24, right: 17), secondary: const Icon(Symbols.new_releases),
secondary: const Icon(Symbols.new_releases), value: _prefs.getBool(kMaterialYouToggleStoreKey) ?? false,
value: _prefs!.getBool(kMaterialYouToggleStoreKey) ?? false, onChanged: (value) {
onChanged: (value) { setState(() {
setState(() { _prefs.setBool(
_prefs!.setBool( kMaterialYouToggleStoreKey,
kMaterialYouToggleStoreKey, value ?? false,
value ?? false, );
); });
}); final th = context.watch<ThemeProvider>();
final th = context.watch<ThemeProvider>(); th.reloadTheme(useMaterial3: value ?? false);
th.reloadTheme(useMaterial3: value ?? false); },
}, ),
),
], ],
), ),
Column( Column(
@ -139,7 +137,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
icon: const Icon(Symbols.save), icon: const Icon(Symbols.save),
onPressed: () { onPressed: () {
sn.setBaseUrl(_serverUrlController.text); sn.setBaseUrl(_serverUrlController.text);
_prefs?.setString( _prefs.setString(
kNetworkServerStoreKey, kNetworkServerStoreKey,
_serverUrlController.text, _serverUrlController.text,
); );
@ -182,7 +180,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
onChanged: (String? value) { onChanged: (String? value) {
if (value == null) return; if (value == null) return;
_serverUrlController.text = value; _serverUrlController.text = value;
_prefs?.setString(kNetworkServerStoreKey, value); _prefs.setString(kNetworkServerStoreKey, value);
context.showSnackbar('settingsNetworkServerSaved'.tr()); context.showSnackbar('settingsNetworkServerSaved'.tr());
setState(() {}); setState(() {});
}, },
@ -208,13 +206,56 @@ class _SettingsScreenState extends State<SettingsScreen> {
trailing: const Icon(Symbols.chevron_right), trailing: const Icon(Symbols.chevron_right),
onTap: () { onTap: () {
_serverUrlController.text = kNetworkServerDefault; _serverUrlController.text = kNetworkServerDefault;
_prefs?.remove(kNetworkServerStoreKey); _prefs.remove(kNetworkServerStoreKey);
context.showSnackbar('settingsNetworkServerSaved'.tr()); context.showSnackbar('settingsNetworkServerSaved'.tr());
setState(() {}); setState(() {});
}, },
), ),
], ],
), ),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('settingsPerformance').bold().fontSize(17).tr().padding(horizontal: 20, bottom: 4),
ListTile(
title: Text('settingsImageQuality').tr(),
subtitle: Text('settingsImageQualityDescription').tr(),
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
leading: const Icon(Symbols.image),
trailing: DropdownButtonHideUnderline(
child: DropdownButton2<FilterQuality>(
value: kImageQualityLevel.values.elementAtOrNull(_prefs.getInt('app_image_quality') ?? 3) ??
FilterQuality.high,
isExpanded: true,
items: kImageQualityLevel.entries
.map(
(item) => DropdownMenuItem<FilterQuality>(
value: item.value,
child: Text(item.key).tr().fontSize(14),
),
)
.toList(),
onChanged: (FilterQuality? value) {
if (value == null) return;
_prefs.setInt('app_image_quality', kImageQualityLevel.values.toList().indexOf(value));
setState(() {});
},
buttonStyleData: const ButtonStyleData(
padding: EdgeInsets.symmetric(
horizontal: 16,
vertical: 5,
),
height: 40,
width: 160,
),
menuItemStyleData: const MenuItemStyleData(
height: 60,
),
),
),
),
],
),
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -231,7 +272,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
), ),
], ],
), ),
].expand((ele) => [ele, const Gap(16)]).toList(), ],
).padding(vertical: 20), ).padding(vertical: 20),
), ),
); );

View File

@ -6,13 +6,11 @@ import 'package:cross_file/cross_file.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:gap/gap.dart'; import 'package:gap/gap.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:receive_sharing_intent/receive_sharing_intent.dart'; import 'package:receive_sharing_intent/receive_sharing_intent.dart';
import 'package:surface/controllers/post_write_controller.dart'; import 'package:surface/controllers/post_write_controller.dart';
import 'package:surface/screens/post/post_editor.dart'; import 'package:surface/screens/post/post_editor.dart';
import 'package:surface/widgets/dialog.dart';
class AppSharingListener extends StatefulWidget { class AppSharingListener extends StatefulWidget {
final Widget child; final Widget child;

View File

@ -1,7 +1,6 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:responsive_framework/responsive_framework.dart'; import 'package:responsive_framework/responsive_framework.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';

View File

@ -458,6 +458,7 @@ class _PostBottomAction extends StatelessWidget {
children: [ children: [
if (showReactions || showComments) if (showReactions || showComments)
Row( Row(
spacing: 8,
children: [ children: [
if (showReactions) if (showReactions)
InkWell( InkWell(
@ -523,8 +524,7 @@ class _PostBottomAction extends StatelessWidget {
); );
}, },
), ),
].expand((ele) => [ele, const Gap(8)]).toList() ],
..removeLast(),
), ),
InkWell( InkWell(
onTap: onShare, onTap: onShare,

View File

@ -1,12 +1,14 @@
import 'dart:io';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:material_symbols_icons/symbols.dart'; import 'package:material_symbols_icons/symbols.dart';
import 'package:provider/provider.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
import 'package:flutter_animate/flutter_animate.dart'; import 'package:flutter_animate/flutter_animate.dart';
// Keep this import to make the web image render work
import 'package:cached_network_image_platform_interface/cached_network_image_platform_interface.dart'; import 'package:cached_network_image_platform_interface/cached_network_image_platform_interface.dart';
import 'package:surface/providers/config.dart';
class UniversalImage extends StatelessWidget { class UniversalImage extends StatelessWidget {
final String url; final String url;
@ -15,7 +17,7 @@ class UniversalImage extends StatelessWidget {
final bool noProgressIndicator; final bool noProgressIndicator;
final bool noErrorWidget; final bool noErrorWidget;
final double? cacheWidth, cacheHeight; final double? cacheWidth, cacheHeight;
final FilterQuality filterQuality; final FilterQuality? filterQuality;
const UniversalImage( const UniversalImage(
this.url, { this.url, {
@ -27,7 +29,7 @@ class UniversalImage extends StatelessWidget {
this.noErrorWidget = false, this.noErrorWidget = false,
this.cacheWidth, this.cacheWidth,
this.cacheHeight, this.cacheHeight,
this.filterQuality = FilterQuality.high, this.filterQuality,
}); });
@override @override
@ -37,7 +39,7 @@ class UniversalImage extends StatelessWidget {
final double? resizeWidth = cacheWidth != null ? (cacheWidth! * devicePixelRatio) : null; final double? resizeWidth = cacheWidth != null ? (cacheWidth! * devicePixelRatio) : null;
return Image( return Image(
filterQuality: filterQuality, filterQuality: filterQuality ?? context.read<ConfigProvider>().imageQuality,
image: kIsWeb image: kIsWeb
? UniversalImage.provider(url) ? UniversalImage.provider(url)
: ResizeImage( : ResizeImage(

View File

@ -289,7 +289,7 @@ SPEC CHECKSUMS:
flutter_udid: 6b2b89780c3dfeecf0047bdf93f622d6416b1c07 flutter_udid: 6b2b89780c3dfeecf0047bdf93f622d6416b1c07
flutter_webrtc: 53c9e1285ab32dfb58afb1e1471416a877e23d7a flutter_webrtc: 53c9e1285ab32dfb58afb1e1471416a877e23d7a
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
gal: 61e868295d28fe67ffa297fae6dacebf56fd53e1 gal: 6a522c75909f1244732d4596d11d6a2f86ff37a5
GoogleAppMeasurement: 987769c4ca6b968f2479fbcc9fe3ce34af454b8e GoogleAppMeasurement: 987769c4ca6b968f2479fbcc9fe3ce34af454b8e
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d

View File

@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts # In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix. # of the product and file versions while build-number is used as the build suffix.
version: 2.1.1+32 version: 2.1.1+33
environment: environment:
sdk: ^3.5.4 sdk: ^3.5.4