From 49cabd1f39079022428eab4beb3a64b2e096ec2f Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sun, 10 Nov 2024 22:14:27 +0800 Subject: [PATCH] :sparkles: Base url --- assets/translations/en-US.json | 5 +- assets/translations/zh-CN.json | 5 +- lib/providers/sn_network.dart | 31 +++++++--- lib/screens/settings.dart | 104 ++++++++++++++++++++++++++++++++ lib/widgets/post/post_item.dart | 2 +- 5 files changed, 135 insertions(+), 12 deletions(-) diff --git a/assets/translations/en-US.json b/assets/translations/en-US.json index 71ac580..83a1e40 100644 --- a/assets/translations/en-US.json +++ b/assets/translations/en-US.json @@ -98,5 +98,8 @@ "settingsNetworkServer": "HyperNet Server", "settingsNetworkServerDescription": "Set the HyperNet server address, choose ours or build your own.", "settingsNetworkServerReset": "Reset to Official Server", - "settingsNetworkServerResetDescription": "Reset to the official server address of Solar Network." + "settingsNetworkServerResetDescription": "Reset to the official server address of Solar Network.", + "settingsNetworkServerPreset": "Present HyperNet Server", + "settingsNetworkServerPresetDescription": "You can choose one of our preset HyperNet server addresses from the list on the right.", + "settingsNetworkServerSaved": "Server address saved." } diff --git a/assets/translations/zh-CN.json b/assets/translations/zh-CN.json index 54dfbbc..8d016f4 100644 --- a/assets/translations/zh-CN.json +++ b/assets/translations/zh-CN.json @@ -98,5 +98,8 @@ "settingsNetworkServer": "HyperNet 服务器", "settingsNetworkServerDescription": "设置 HyperNet 服务器地址,选择我们提供的,或者自己搭建。", "settingsNetworkServerReset": "重设为官方服务器", - "settingsNetworkServerResetDescription": "重设为 Solar Network 的服务器地址。" + "settingsNetworkServerResetDescription": "重设为 Solar Network 的服务器地址。", + "settingsNetworkServerPreset": "预设的 HyperNet 服务器", + "settingsNetworkServerPresetDescription": "你可以在旁边的列表中选择我们提供的预设 HyperNet 服务器地址。", + "settingsNetworkServerSaved": "服务器地址已保存。" } diff --git a/lib/providers/sn_network.dart b/lib/providers/sn_network.dart index 1bb7456..22a21f0 100644 --- a/lib/providers/sn_network.dart +++ b/lib/providers/sn_network.dart @@ -4,25 +4,30 @@ import 'dart:developer'; import 'package:dio/dio.dart'; import 'package:dio_smart_retry/dio_smart_retry.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:surface/providers/adapters/sn_network_universal.dart'; -const kUseLocalNetwork = true; - const kAtkStoreKey = 'nex_user_atk'; const kRtkStoreKey = 'nex_user_rtk'; +const kNetworkServerDefault = 'https://api.sn-next.solsynth.dev'; +const kNetworkServerStoreKey = 'app_server_url'; + +const kNetworkServerDirectory = [ + ('SN Preview', 'https://api.sn-next.solsynth.dev'), + ('SN Stable', 'https://api.sn.solsynth.dev'), + ('Local', 'http://localhost:8001'), +]; + class SnNetworkProvider { late Dio client; + late final SharedPreferences _prefs; late final FlutterSecureStorage _storage = FlutterSecureStorage(); SnNetworkProvider() { client = Dio(); - client.options.baseUrl = kUseLocalNetwork - ? 'http://localhost:8001' - : 'https://api.sn.solsynth.dev'; - client.interceptors.add(RetryInterceptor( dio: client, retries: 3, @@ -86,6 +91,12 @@ class SnNetworkProvider { ); client = addClientAdapter(client); + + SharedPreferences.getInstance().then((prefs) { + _prefs = prefs; + client.options.baseUrl = + _prefs.getString(kNetworkServerStoreKey) ?? kNetworkServerDefault; + }); } String getAttachmentUrl(String ky) { @@ -112,9 +123,7 @@ class SnNetworkProvider { if (rtk == null) return null; final dio = Dio(); - dio.options.baseUrl = kUseLocalNetwork - ? 'http://localhost:8001' - : 'https://api.sn.solsynth.dev'; + dio.options.baseUrl = client.options.baseUrl; final resp = await dio.post('/cgi/id/auth/token', data: { 'grant_type': 'refresh_token', @@ -127,4 +136,8 @@ class SnNetworkProvider { return atk; } + + void setBaseUrl(String url) { + client.options.baseUrl = url; + } } diff --git a/lib/screens/settings.dart b/lib/screens/settings.dart index f5af0f8..a5bbc7f 100644 --- a/lib/screens/settings.dart +++ b/lib/screens/settings.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -10,8 +11,10 @@ import 'package:path_provider/path_provider.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:styled_widget/styled_widget.dart'; +import 'package:surface/providers/sn_network.dart'; import 'package:surface/providers/theme.dart'; import 'package:surface/theme.dart'; +import 'package:surface/widgets/dialog.dart'; import 'package:surface/widgets/navigation/app_scaffold.dart'; class SettingsScreen extends StatefulWidget { @@ -25,6 +28,8 @@ class _SettingsScreenState extends State { SharedPreferences? _prefs; String _docBasepath = '/'; + final TextEditingController _serverUrlController = TextEditingController(); + @override void initState() { super.initState(); @@ -37,12 +42,22 @@ class _SettingsScreenState extends State { SharedPreferences.getInstance().then((prefs) { setState(() { _prefs = prefs; + _serverUrlController.text = + prefs.getString(kNetworkServerStoreKey) ?? kNetworkServerDefault; }); }); } + @override + void dispose() { + _serverUrlController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { + final sn = context.read(); + return AppScaffold( body: SingleChildScrollView( child: Column( @@ -127,6 +142,95 @@ class _SettingsScreenState extends State { .fontSize(17) .tr() .padding(horizontal: 20), + TextField( + controller: _serverUrlController, + decoration: InputDecoration( + border: const OutlineInputBorder(), + labelText: 'settingsNetworkServer'.tr(), + helperText: 'settingsNetworkServerDescription'.tr(), + prefixIcon: const Icon(Symbols.dns), + suffixIcon: IconButton( + icon: const Icon(Symbols.save), + onPressed: () { + sn.setBaseUrl(_serverUrlController.text); + _prefs?.setString( + kNetworkServerStoreKey, + _serverUrlController.text, + ); + context.showSnackbar('settingsNetworkServerSaved'.tr()); + setState(() {}); + }, + ), + ), + onTapOutside: (_) => + FocusManager.instance.primaryFocus?.unfocus(), + ).padding(horizontal: 16, top: 8, bottom: 4), + ListTile( + title: Text('settingsNetworkServerPreset').tr(), + subtitle: Text('settingsNetworkServerPresetDescription').tr(), + contentPadding: const EdgeInsets.symmetric(horizontal: 24), + leading: const Icon(Symbols.lists), + trailing: DropdownButtonHideUnderline( + child: DropdownButton2( + isExpanded: true, + items: [ + ...kNetworkServerDirectory, + if (!kNetworkServerDirectory + .map((ele) => ele.$2) + .contains(_serverUrlController.text)) + ('Custom', _serverUrlController.text), + ] + .map( + (item) => DropdownMenuItem( + value: item.$2, + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(item.$1).fontSize(14), + Text(item.$2, overflow: TextOverflow.ellipsis) + .fontSize(11) + ], + ), + ), + ) + .toList(), + value: _serverUrlController.text, + onChanged: (String? value) { + if (value == null) return; + _serverUrlController.text = value; + _prefs?.setString(kNetworkServerStoreKey, value); + context.showSnackbar('settingsNetworkServerSaved'.tr()); + setState(() {}); + }, + buttonStyleData: const ButtonStyleData( + padding: EdgeInsets.symmetric( + horizontal: 16, + vertical: 5, + ), + height: 40, + width: 140, + ), + menuItemStyleData: const MenuItemStyleData( + height: 60, + ), + ), + ), + ), + ListTile( + title: Text('settingsNetworkServerReset').tr(), + subtitle: Text('settingsNetworkServerResetDescription').tr(), + contentPadding: const EdgeInsets.symmetric(horizontal: 24), + leading: const Icon(Symbols.reset_wrench), + trailing: const Icon(Symbols.chevron_right), + onTap: () { + _serverUrlController.text = kNetworkServerDefault; + _prefs?.remove(kNetworkServerStoreKey); + context.showSnackbar('settingsNetworkServerSaved'.tr()); + setState(() {}); + }, + ), ], ), ].expand((ele) => [ele, const Gap(16)]).toList(), diff --git a/lib/widgets/post/post_item.dart b/lib/widgets/post/post_item.dart index c2dd9fb..de5acd2 100644 --- a/lib/widgets/post/post_item.dart +++ b/lib/widgets/post/post_item.dart @@ -34,7 +34,7 @@ class PostItem extends StatelessWidget { class _PostBottomAction extends StatelessWidget { final SnPost data; - const _PostBottomAction({super.key, required this.data}); + const _PostBottomAction({required this.data}); @override Widget build(BuildContext context) {