Compare commits
2 Commits
8a628823e0
...
65a8f1e6c3
Author | SHA1 | Date | |
---|---|---|---|
65a8f1e6c3 | |||
2671ffad4b |
16
README.md
16
README.md
@ -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.
|
|
@ -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.",
|
||||||
|
@ -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 的版本信息。",
|
||||||
|
@ -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": "發佈動態"
|
||||||
}
|
}
|
||||||
|
@ -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": "釋出動態"
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
43
lib/providers/config.dart
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -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;
|
||||||
|
@ -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';
|
||||||
|
@ -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,
|
||||||
|
@ -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(
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user