Compare commits
No commits in common. "5364aecf745cea2b524bc286ac9cf22bbff50052" and "c1e10916ee764fc40a2ccac2fad65ad247816717" have entirely different histories.
5364aecf74
...
c1e10916ee
@ -14,7 +14,6 @@
|
|||||||
"screenAccountPublisherNew": "New Publisher",
|
"screenAccountPublisherNew": "New Publisher",
|
||||||
"screenAccountPublisherEdit": "Edit Publisher",
|
"screenAccountPublisherEdit": "Edit Publisher",
|
||||||
"screenAccountProfileEdit": "Edit Profile",
|
"screenAccountProfileEdit": "Edit Profile",
|
||||||
"screenSettings": "Settings",
|
|
||||||
"dialogOkay": "Okay",
|
"dialogOkay": "Okay",
|
||||||
"dialogCancel": "Cancel",
|
"dialogCancel": "Cancel",
|
||||||
"dialogConfirm": "Confirm",
|
"dialogConfirm": "Confirm",
|
||||||
@ -37,9 +36,6 @@
|
|||||||
"report": "Report",
|
"report": "Report",
|
||||||
"repost": "Repost",
|
"repost": "Repost",
|
||||||
"reply": "Reply",
|
"reply": "Reply",
|
||||||
"untitled": "Untitled",
|
|
||||||
"postDetail": "Post detail",
|
|
||||||
"postNoun": "Post",
|
|
||||||
"fieldUsername": "Username",
|
"fieldUsername": "Username",
|
||||||
"fieldNickname": "Nickname",
|
"fieldNickname": "Nickname",
|
||||||
"fieldEmail": "Email address",
|
"fieldEmail": "Email address",
|
||||||
@ -84,26 +80,5 @@
|
|||||||
"postPublish": "Publish",
|
"postPublish": "Publish",
|
||||||
"postEditingNotice": "You're about to editing a post that posted {}.",
|
"postEditingNotice": "You're about to editing a post that posted {}.",
|
||||||
"postReplyingNotice": "You're about to reply to a post that posted {}.",
|
"postReplyingNotice": "You're about to reply to a post that posted {}.",
|
||||||
"postRepostingNotice": "You're about to repost a post that posted {}.",
|
"postRepostingNotice": "You're about to repost a post that posted {}."
|
||||||
"postReact": "React",
|
|
||||||
"postComments": {
|
|
||||||
"zero": "Comment",
|
|
||||||
"one": "{} comment",
|
|
||||||
"other": "{} comments"
|
|
||||||
},
|
|
||||||
"settingsAppearance": "Appearance",
|
|
||||||
"settingsBackgroundImage": "Background Image",
|
|
||||||
"settingsBackgroundImageDescription": "Set the background image that will be applied globally.",
|
|
||||||
"settingsBackgroundImageClear": "Clear Existing Background Image",
|
|
||||||
"settingsBackgroundImageClearDescription": "Reset the background image to blank.",
|
|
||||||
"settingsThemeMaterial3": "Use Material You Design",
|
|
||||||
"settingsThemeMaterial3Description": "Set the application theme to Material 3 Design.",
|
|
||||||
"settingsNetwork": "Network",
|
|
||||||
"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.",
|
|
||||||
"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."
|
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
"screenAccountPublisherNew": "新建发布者",
|
"screenAccountPublisherNew": "新建发布者",
|
||||||
"screenAccountPublisherEdit": "编辑发布者",
|
"screenAccountPublisherEdit": "编辑发布者",
|
||||||
"screenAccountProfileEdit": "编辑资料",
|
"screenAccountProfileEdit": "编辑资料",
|
||||||
"screenSettings": "设置",
|
|
||||||
"dialogOkay": "好的",
|
"dialogOkay": "好的",
|
||||||
"dialogCancel": "取消",
|
"dialogCancel": "取消",
|
||||||
"dialogConfirm": "确认",
|
"dialogConfirm": "确认",
|
||||||
@ -37,9 +36,6 @@
|
|||||||
"report": "检举",
|
"report": "检举",
|
||||||
"repost": "转帖",
|
"repost": "转帖",
|
||||||
"reply": "回贴",
|
"reply": "回贴",
|
||||||
"untitled": "无题",
|
|
||||||
"postDetail": "帖子详情",
|
|
||||||
"postNoun": "帖子",
|
|
||||||
"fieldUsername": "用户名",
|
"fieldUsername": "用户名",
|
||||||
"fieldNickname": "显示名",
|
"fieldNickname": "显示名",
|
||||||
"fieldEmail": "电子邮箱地址",
|
"fieldEmail": "电子邮箱地址",
|
||||||
@ -84,26 +80,5 @@
|
|||||||
"postPublish": "发布",
|
"postPublish": "发布",
|
||||||
"postEditingNotice": "你正在修改由 {} 发布的帖子。",
|
"postEditingNotice": "你正在修改由 {} 发布的帖子。",
|
||||||
"postReplyingNotice": "你正在回复由 {} 发布的帖子。",
|
"postReplyingNotice": "你正在回复由 {} 发布的帖子。",
|
||||||
"postRepostingNotice": "你正在转发由 {} 发布的帖子。",
|
"postRepostingNotice": "你正在转发由 {} 发布的帖子。"
|
||||||
"postReact": "反应",
|
|
||||||
"postComments": {
|
|
||||||
"zero": "评论",
|
|
||||||
"one": "{} 条评论",
|
|
||||||
"other": "{} 条评论"
|
|
||||||
},
|
|
||||||
"settingsAppearance": "外观",
|
|
||||||
"settingsBackgroundImage": "背景图片",
|
|
||||||
"settingsBackgroundImageDescription": "设置应用全局生效的的背景图片。",
|
|
||||||
"settingsBackgroundImageClear": "清除现存背景图",
|
|
||||||
"settingsBackgroundImageClearDescription": "将应用背景图重置为空白。",
|
|
||||||
"settingsThemeMaterial3": "使用 Material You 设计范式",
|
|
||||||
"settingsThemeMaterial3Description": "将应用主题设置为 Material 3 设计范式的主题。",
|
|
||||||
"settingsNetwork": "网络",
|
|
||||||
"settingsNetworkServer": "HyperNet 服务器",
|
|
||||||
"settingsNetworkServerDescription": "设置 HyperNet 服务器地址,选择我们提供的,或者自己搭建。",
|
|
||||||
"settingsNetworkServerReset": "重设为官方服务器",
|
|
||||||
"settingsNetworkServerResetDescription": "重设为 Solar Network 的服务器地址。",
|
|
||||||
"settingsNetworkServerPreset": "预设的 HyperNet 服务器",
|
|
||||||
"settingsNetworkServerPresetDescription": "你可以在旁边的列表中选择我们提供的预设 HyperNet 服务器地址。",
|
|
||||||
"settingsNetworkServerSaved": "服务器地址已保存。"
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import 'package:croppy/croppy.dart';
|
import 'package:croppy/croppy.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:easy_localization_loader/easy_localization_loader.dart';
|
import 'package:easy_localization_loader/easy_localization_loader.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:relative_time/relative_time.dart';
|
import 'package:relative_time/relative_time.dart';
|
||||||
@ -16,10 +15,6 @@ void main() async {
|
|||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
await EasyLocalization.ensureInitialized();
|
await EasyLocalization.ensureInitialized();
|
||||||
|
|
||||||
if (!kReleaseMode) {
|
|
||||||
debugInvertOversizedImages = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
runApp(const SolianApp());
|
runApp(const SolianApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +37,25 @@ class SolianApp extends StatelessWidget {
|
|||||||
ChangeNotifierProvider(create: (ctx) => UserProvider(ctx)),
|
ChangeNotifierProvider(create: (ctx) => UserProvider(ctx)),
|
||||||
ChangeNotifierProvider(create: (_) => ThemeProvider()),
|
ChangeNotifierProvider(create: (_) => ThemeProvider()),
|
||||||
],
|
],
|
||||||
child: AppMainContent(),
|
child: Builder(builder: (context) {
|
||||||
|
// Initialize some providers
|
||||||
|
context.read<UserProvider>();
|
||||||
|
|
||||||
|
final th = context.watch<ThemeProvider>();
|
||||||
|
|
||||||
|
return MaterialApp.router(
|
||||||
|
theme: th.theme.light,
|
||||||
|
darkTheme: th.theme.dark,
|
||||||
|
locale: context.locale,
|
||||||
|
supportedLocales: context.supportedLocales,
|
||||||
|
localizationsDelegates: [
|
||||||
|
CroppyLocalizations.delegate,
|
||||||
|
RelativeTimeLocalizations.delegate,
|
||||||
|
...context.localizationDelegates,
|
||||||
|
],
|
||||||
|
routerConfig: appRouter,
|
||||||
|
);
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
breakpoints: [
|
breakpoints: [
|
||||||
@ -53,27 +66,3 @@ class SolianApp extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppMainContent extends StatelessWidget {
|
|
||||||
const AppMainContent({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
context.read<UserProvider>();
|
|
||||||
|
|
||||||
final th = context.watch<ThemeProvider>();
|
|
||||||
|
|
||||||
return MaterialApp.router(
|
|
||||||
theme: th.theme?.light,
|
|
||||||
darkTheme: th.theme?.dark,
|
|
||||||
locale: context.locale,
|
|
||||||
supportedLocales: context.supportedLocales,
|
|
||||||
localizationsDelegates: [
|
|
||||||
CroppyLocalizations.delegate,
|
|
||||||
RelativeTimeLocalizations.delegate,
|
|
||||||
...context.localizationDelegates,
|
|
||||||
],
|
|
||||||
routerConfig: appRouter,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -4,30 +4,25 @@ import 'dart:developer';
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:dio_smart_retry/dio_smart_retry.dart';
|
import 'package:dio_smart_retry/dio_smart_retry.dart';
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.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';
|
import 'package:surface/providers/adapters/sn_network_universal.dart';
|
||||||
|
|
||||||
|
const kUseLocalNetwork = true;
|
||||||
|
|
||||||
const kAtkStoreKey = 'nex_user_atk';
|
const kAtkStoreKey = 'nex_user_atk';
|
||||||
const kRtkStoreKey = 'nex_user_rtk';
|
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 {
|
class SnNetworkProvider {
|
||||||
late Dio client;
|
late Dio client;
|
||||||
|
|
||||||
late final SharedPreferences _prefs;
|
|
||||||
late final FlutterSecureStorage _storage = FlutterSecureStorage();
|
late final FlutterSecureStorage _storage = FlutterSecureStorage();
|
||||||
|
|
||||||
SnNetworkProvider() {
|
SnNetworkProvider() {
|
||||||
client = Dio();
|
client = Dio();
|
||||||
|
|
||||||
|
client.options.baseUrl = kUseLocalNetwork
|
||||||
|
? 'http://localhost:8001'
|
||||||
|
: 'https://api.sn.solsynth.dev';
|
||||||
|
|
||||||
client.interceptors.add(RetryInterceptor(
|
client.interceptors.add(RetryInterceptor(
|
||||||
dio: client,
|
dio: client,
|
||||||
retries: 3,
|
retries: 3,
|
||||||
@ -91,12 +86,6 @@ class SnNetworkProvider {
|
|||||||
);
|
);
|
||||||
|
|
||||||
client = addClientAdapter(client);
|
client = addClientAdapter(client);
|
||||||
|
|
||||||
SharedPreferences.getInstance().then((prefs) {
|
|
||||||
_prefs = prefs;
|
|
||||||
client.options.baseUrl =
|
|
||||||
_prefs.getString(kNetworkServerStoreKey) ?? kNetworkServerDefault;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String getAttachmentUrl(String ky) {
|
String getAttachmentUrl(String ky) {
|
||||||
@ -123,7 +112,9 @@ class SnNetworkProvider {
|
|||||||
if (rtk == null) return null;
|
if (rtk == null) return null;
|
||||||
|
|
||||||
final dio = Dio();
|
final dio = Dio();
|
||||||
dio.options.baseUrl = client.options.baseUrl;
|
dio.options.baseUrl = kUseLocalNetwork
|
||||||
|
? 'http://localhost:8001'
|
||||||
|
: 'https://api.sn.solsynth.dev';
|
||||||
|
|
||||||
final resp = await dio.post('/cgi/id/auth/token', data: {
|
final resp = await dio.post('/cgi/id/auth/token', data: {
|
||||||
'grant_type': 'refresh_token',
|
'grant_type': 'refresh_token',
|
||||||
@ -136,8 +127,4 @@ class SnNetworkProvider {
|
|||||||
|
|
||||||
return atk;
|
return atk;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setBaseUrl(String url) {
|
|
||||||
client.options.baseUrl = url;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,19 +2,9 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:surface/theme.dart';
|
import 'package:surface/theme.dart';
|
||||||
|
|
||||||
class ThemeProvider extends ChangeNotifier {
|
class ThemeProvider extends ChangeNotifier {
|
||||||
ThemeSet? theme;
|
late ThemeSet theme;
|
||||||
|
|
||||||
ThemeProvider() {
|
ThemeProvider() {
|
||||||
createAppThemeSet().then((value) {
|
theme = createAppThemeSet();
|
||||||
theme = value;
|
|
||||||
notifyListeners();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void reloadTheme({bool? useMaterial3}) {
|
|
||||||
createAppThemeSet().then((value) {
|
|
||||||
theme = value;
|
|
||||||
notifyListeners();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,7 @@ import 'package:surface/screens/auth/login.dart';
|
|||||||
import 'package:surface/screens/auth/register.dart';
|
import 'package:surface/screens/auth/register.dart';
|
||||||
import 'package:surface/screens/explore.dart';
|
import 'package:surface/screens/explore.dart';
|
||||||
import 'package:surface/screens/home.dart';
|
import 'package:surface/screens/home.dart';
|
||||||
import 'package:surface/screens/post/post_detail.dart';
|
|
||||||
import 'package:surface/screens/post/post_editor.dart';
|
import 'package:surface/screens/post/post_editor.dart';
|
||||||
import 'package:surface/screens/settings.dart';
|
|
||||||
import 'package:surface/types/post.dart';
|
|
||||||
import 'package:surface/widgets/navigation/app_scaffold.dart';
|
import 'package:surface/widgets/navigation/app_scaffold.dart';
|
||||||
|
|
||||||
final appRouter = GoRouter(
|
final appRouter = GoRouter(
|
||||||
@ -60,14 +57,6 @@ final appRouter = GoRouter(
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
GoRoute(
|
|
||||||
path: '/post/:slug',
|
|
||||||
name: 'postDetail',
|
|
||||||
builder: (context, state) => PostDetailScreen(
|
|
||||||
slug: state.pathParameters['slug']!,
|
|
||||||
preload: state.extra as SnPost?,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
ShellRoute(
|
ShellRoute(
|
||||||
@ -110,18 +99,5 @@ final appRouter = GoRouter(
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
ShellRoute(
|
|
||||||
builder: (context, state, child) => AppScaffold(
|
|
||||||
body: child,
|
|
||||||
autoImplyAppBar: true,
|
|
||||||
),
|
|
||||||
routes: [
|
|
||||||
GoRoute(
|
|
||||||
path: '/settings',
|
|
||||||
name: 'settings',
|
|
||||||
builder: (context, state) => const SettingsScreen(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -20,14 +20,6 @@ class AccountScreen extends StatelessWidget {
|
|||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text("screenAccount").tr(),
|
title: Text("screenAccount").tr(),
|
||||||
actions: [
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Symbols.settings, fill: 1),
|
|
||||||
onPressed: () {
|
|
||||||
GoRouter.of(context).pushNamed('settings');
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
child: ua.isAuthorized
|
child: ua.isAuthorized
|
||||||
|
@ -171,16 +171,7 @@ class _ExploreScreenState extends State<ExploreScreen> {
|
|||||||
hasReachedMax: _postCount != null && _posts.length >= _postCount!,
|
hasReachedMax: _postCount != null && _posts.length >= _postCount!,
|
||||||
onFetchData: _fetchPosts,
|
onFetchData: _fetchPosts,
|
||||||
itemBuilder: (context, idx) {
|
itemBuilder: (context, idx) {
|
||||||
return GestureDetector(
|
return PostItem(data: _posts[idx]);
|
||||||
child: PostItem(data: _posts[idx]),
|
|
||||||
onTap: () {
|
|
||||||
GoRouter.of(context).pushNamed(
|
|
||||||
'postDetail',
|
|
||||||
pathParameters: {'slug': _posts[idx].id.toString()},
|
|
||||||
extra: _posts[idx],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
separatorBuilder: (context, index) => const Divider(),
|
separatorBuilder: (context, index) => const Divider(),
|
||||||
)
|
)
|
||||||
|
@ -1,102 +0,0 @@
|
|||||||
import 'dart:math' as math;
|
|
||||||
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:go_router/go_router.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
|
||||||
import 'package:surface/providers/sn_attachment.dart';
|
|
||||||
import 'package:surface/providers/sn_network.dart';
|
|
||||||
import 'package:surface/types/post.dart';
|
|
||||||
import 'package:surface/widgets/dialog.dart';
|
|
||||||
import 'package:surface/widgets/loading_indicator.dart';
|
|
||||||
import 'package:surface/widgets/navigation/app_scaffold.dart';
|
|
||||||
import 'package:surface/widgets/post/post_item.dart';
|
|
||||||
|
|
||||||
class PostDetailScreen extends StatefulWidget {
|
|
||||||
final String slug;
|
|
||||||
final SnPost? preload;
|
|
||||||
const PostDetailScreen({
|
|
||||||
super.key,
|
|
||||||
required this.slug,
|
|
||||||
this.preload,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<PostDetailScreen> createState() => _PostDetailScreenState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _PostDetailScreenState extends State<PostDetailScreen> {
|
|
||||||
bool _isBusy = false;
|
|
||||||
|
|
||||||
SnPost? _data;
|
|
||||||
|
|
||||||
void _fetchPost() async {
|
|
||||||
setState(() => _isBusy = true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
final sn = context.read<SnNetworkProvider>();
|
|
||||||
final attach = context.read<SnAttachmentProvider>();
|
|
||||||
final resp = await sn.client.get('/cgi/co/posts/${widget.slug}');
|
|
||||||
if (!mounted) return;
|
|
||||||
final attachments = await attach.getMultiple(
|
|
||||||
resp.data['body']['attachments']?.cast<String>() ?? [],
|
|
||||||
);
|
|
||||||
if (!mounted) return;
|
|
||||||
setState(() {
|
|
||||||
_data = SnPost.fromJson(resp.data).copyWith(
|
|
||||||
preload: SnPostPreload(
|
|
||||||
attachments: attachments,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
context.showErrorDialog(err);
|
|
||||||
} finally {
|
|
||||||
setState(() => _isBusy = false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
if (widget.preload != null) {
|
|
||||||
_data = widget.preload;
|
|
||||||
}
|
|
||||||
_fetchPost();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AppScaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
leading: BackButton(
|
|
||||||
onPressed: () {
|
|
||||||
if (GoRouter.of(context).canPop()) {
|
|
||||||
Navigator.pop(context);
|
|
||||||
}
|
|
||||||
GoRouter.of(context).replaceNamed('explore');
|
|
||||||
},
|
|
||||||
),
|
|
||||||
flexibleSpace: Column(
|
|
||||||
children: [
|
|
||||||
Text(_data?.body['title'] ?? 'postNoun'.tr())
|
|
||||||
.textStyle(Theme.of(context).textTheme.titleLarge!)
|
|
||||||
.textColor(Colors.white),
|
|
||||||
Text('postDetail')
|
|
||||||
.tr()
|
|
||||||
.textColor(Colors.white.withAlpha((255 * 0.9).round())),
|
|
||||||
],
|
|
||||||
).padding(top: math.max(MediaQuery.of(context).padding.top, 8)),
|
|
||||||
),
|
|
||||||
body: SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
LoadingIndicator(isActive: _isBusy),
|
|
||||||
if (_data != null) PostItem(data: _data!),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,3 @@
|
|||||||
import 'dart:math' as math;
|
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.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';
|
||||||
@ -278,14 +275,14 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
|
|||||||
),
|
),
|
||||||
flexibleSpace: Column(
|
flexibleSpace: Column(
|
||||||
children: [
|
children: [
|
||||||
Text(_title ?? 'untitled'.tr())
|
Text(_title ?? 'Untitled')
|
||||||
.textStyle(Theme.of(context).textTheme.titleLarge!)
|
.textStyle(Theme.of(context).textTheme.titleLarge!)
|
||||||
.textColor(Colors.white),
|
.textColor(Colors.white),
|
||||||
Text(_kTitleMap[widget.mode]!)
|
Text(_kTitleMap[widget.mode]!)
|
||||||
.tr()
|
.tr()
|
||||||
.textColor(Colors.white.withAlpha((255 * 0.9).round())),
|
.textColor(Colors.white.withAlpha((255 * 0.9).round())),
|
||||||
],
|
],
|
||||||
).padding(top: math.max(MediaQuery.of(context).padding.top, 8)),
|
).padding(top: MediaQuery.of(context).padding.top),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Symbols.tune),
|
icon: const Icon(Symbols.tune),
|
||||||
@ -471,17 +468,8 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
|
|||||||
onTapOutside: (_) =>
|
onTapOutside: (_) =>
|
||||||
FocusManager.instance.primaryFocus?.unfocus(),
|
FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
)
|
)
|
||||||
]
|
].expand((ele) => [ele, const Gap(8)]).toList()
|
||||||
.expandIndexed(
|
..removeLast(),
|
||||||
(idx, ele) => [
|
|
||||||
if (idx != 0 ||
|
|
||||||
![_editingOg, _replyingTo, _repostingTo]
|
|
||||||
.any((x) => x != null))
|
|
||||||
const Gap(8),
|
|
||||||
ele,
|
|
||||||
],
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,241 +0,0 @@
|
|||||||
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';
|
|
||||||
import 'package:gap/gap.dart';
|
|
||||||
import 'package:image_picker/image_picker.dart';
|
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
|
||||||
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 {
|
|
||||||
const SettingsScreen({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<SettingsScreen> createState() => _SettingsScreenState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _SettingsScreenState extends State<SettingsScreen> {
|
|
||||||
SharedPreferences? _prefs;
|
|
||||||
String _docBasepath = '/';
|
|
||||||
|
|
||||||
final TextEditingController _serverUrlController = TextEditingController();
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
getApplicationDocumentsDirectory().then((dir) {
|
|
||||||
_docBasepath = dir.path;
|
|
||||||
if (mounted) {
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
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<SnNetworkProvider>();
|
|
||||||
|
|
||||||
return AppScaffold(
|
|
||||||
body: SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text('settingsAppearance')
|
|
||||||
.bold()
|
|
||||||
.fontSize(17)
|
|
||||||
.tr()
|
|
||||||
.padding(horizontal: 20, bottom: 4),
|
|
||||||
if (!kIsWeb)
|
|
||||||
ListTile(
|
|
||||||
title: Text('settingsBackgroundImage').tr(),
|
|
||||||
subtitle: Text('settingsBackgroundImageDescription').tr(),
|
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
|
|
||||||
leading: const Icon(Symbols.image),
|
|
||||||
trailing: const Icon(Symbols.chevron_right),
|
|
||||||
onTap: () async {
|
|
||||||
final image = await ImagePicker()
|
|
||||||
.pickImage(source: ImageSource.gallery);
|
|
||||||
if (image == null) return;
|
|
||||||
|
|
||||||
await File(image.path)
|
|
||||||
.copy('$_docBasepath/app_background_image');
|
|
||||||
|
|
||||||
setState(() {});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
if (!kIsWeb)
|
|
||||||
FutureBuilder<bool>(
|
|
||||||
future:
|
|
||||||
File('$_docBasepath/app_background_image').exists(),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (!snapshot.hasData || !snapshot.data!) {
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ListTile(
|
|
||||||
title: Text('settingsBackgroundImageClear').tr(),
|
|
||||||
subtitle:
|
|
||||||
Text('settingsBackgroundImageClearDescription')
|
|
||||||
.tr(),
|
|
||||||
contentPadding:
|
|
||||||
const EdgeInsets.symmetric(horizontal: 24),
|
|
||||||
leading: const Icon(Symbols.texture),
|
|
||||||
trailing: const Icon(Symbols.chevron_right),
|
|
||||||
onTap: () {
|
|
||||||
File('$_docBasepath/app_background_image')
|
|
||||||
.deleteSync();
|
|
||||||
setState(() {});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
if (_prefs != null)
|
|
||||||
CheckboxListTile(
|
|
||||||
title: Text('settingsThemeMaterial3').tr(),
|
|
||||||
subtitle: Text('settingsThemeMaterial3Description').tr(),
|
|
||||||
contentPadding: const EdgeInsets.only(left: 24, right: 17),
|
|
||||||
secondary: const Icon(Symbols.new_releases),
|
|
||||||
value: _prefs!.getBool(kMaterialYouToggleStoreKey) ?? false,
|
|
||||||
onChanged: (value) {
|
|
||||||
setState(() {
|
|
||||||
_prefs!.setBool(
|
|
||||||
kMaterialYouToggleStoreKey,
|
|
||||||
value ?? false,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
final th = context.watch<ThemeProvider>();
|
|
||||||
th.reloadTheme(useMaterial3: value ?? false);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text('settingsNetwork')
|
|
||||||
.bold()
|
|
||||||
.fontSize(17)
|
|
||||||
.tr()
|
|
||||||
.padding(horizontal: 20, bottom: 4),
|
|
||||||
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<String>(
|
|
||||||
isExpanded: true,
|
|
||||||
items: [
|
|
||||||
...kNetworkServerDirectory,
|
|
||||||
if (!kNetworkServerDirectory
|
|
||||||
.map((ele) => ele.$2)
|
|
||||||
.contains(_serverUrlController.text))
|
|
||||||
('Custom', _serverUrlController.text),
|
|
||||||
]
|
|
||||||
.map(
|
|
||||||
(item) => DropdownMenuItem<String>(
|
|
||||||
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(),
|
|
||||||
).padding(vertical: 20),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,4 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
|
||||||
|
|
||||||
const kMaterialYouToggleStoreKey = 'app_theme_material_you';
|
|
||||||
|
|
||||||
class ThemeSet {
|
class ThemeSet {
|
||||||
ThemeData light;
|
ThemeData light;
|
||||||
@ -10,35 +7,21 @@ class ThemeSet {
|
|||||||
ThemeSet({required this.light, required this.dark});
|
ThemeSet({required this.light, required this.dark});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<ThemeSet> createAppThemeSet({bool? useMaterial3}) async {
|
ThemeSet createAppThemeSet() {
|
||||||
return ThemeSet(
|
return ThemeSet(
|
||||||
light: await createAppTheme(Brightness.light, useMaterial3: useMaterial3),
|
light: createAppTheme(Brightness.light),
|
||||||
dark: await createAppTheme(Brightness.dark, useMaterial3: useMaterial3),
|
dark: createAppTheme(Brightness.dark),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<ThemeData> createAppTheme(
|
ThemeData createAppTheme(Brightness brightness) {
|
||||||
Brightness brightness, {
|
|
||||||
bool? useMaterial3,
|
|
||||||
}) async {
|
|
||||||
final prefs = await SharedPreferences.getInstance();
|
|
||||||
|
|
||||||
final colorScheme = ColorScheme.fromSeed(
|
|
||||||
seedColor: Colors.indigo,
|
|
||||||
brightness: brightness,
|
|
||||||
);
|
|
||||||
|
|
||||||
return ThemeData(
|
return ThemeData(
|
||||||
useMaterial3:
|
useMaterial3: false,
|
||||||
useMaterial3 ?? (prefs.getBool(kMaterialYouToggleStoreKey) ?? false),
|
colorScheme: ColorScheme.fromSeed(
|
||||||
colorScheme: colorScheme,
|
seedColor: Colors.indigo,
|
||||||
brightness: brightness,
|
brightness: brightness,
|
||||||
iconTheme: IconThemeData(
|
|
||||||
fill: 0,
|
|
||||||
weight: 400,
|
|
||||||
opticalSize: 20,
|
|
||||||
color: colorScheme.onSurface,
|
|
||||||
),
|
),
|
||||||
scaffoldBackgroundColor: Colors.transparent,
|
brightness: brightness,
|
||||||
|
iconTheme: const IconThemeData(fill: 0, weight: 400, opticalSize: 20),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -23,14 +23,10 @@ class AttachmentItem extends StatelessWidget {
|
|||||||
case 'image':
|
case 'image':
|
||||||
return Hero(
|
return Hero(
|
||||||
tag: 'attachment-${data.rid}-$heroTag',
|
tag: 'attachment-${data.rid}-$heroTag',
|
||||||
child: LayoutBuilder(builder: (context, constraints) {
|
child: UniversalImage(
|
||||||
return UniversalImage(
|
sn.getAttachmentUrl(data.rid),
|
||||||
sn.getAttachmentUrl(data.rid),
|
fit: BoxFit.cover,
|
||||||
fit: BoxFit.cover,
|
),
|
||||||
cacheHeight: constraints.maxHeight,
|
|
||||||
cacheWidth: constraints.maxWidth,
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
return const Placeholder();
|
return const Placeholder();
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
|
||||||
|
|
||||||
class AppBackground extends StatelessWidget {
|
class AppBackground extends StatelessWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
@ -10,52 +6,6 @@ class AppBackground extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
|
return ScaffoldMessenger(child: child);
|
||||||
|
|
||||||
return ScaffoldMessenger(
|
|
||||||
child: FutureBuilder(
|
|
||||||
future:
|
|
||||||
kIsWeb ? Future.value(null) : getApplicationDocumentsDirectory(),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (snapshot.hasData) {
|
|
||||||
final path = '${snapshot.data!.path}/app_background_image';
|
|
||||||
final file = File(path);
|
|
||||||
if (file.existsSync()) {
|
|
||||||
return Container(
|
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: LayoutBuilder(
|
|
||||||
builder: (context, constraints) {
|
|
||||||
return Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
backgroundBlendMode: BlendMode.darken,
|
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
image: DecorationImage(
|
|
||||||
opacity: 0.2,
|
|
||||||
image: ResizeImage(
|
|
||||||
FileImage(file),
|
|
||||||
width: (constraints.maxWidth * devicePixelRatio)
|
|
||||||
.round(),
|
|
||||||
height: (constraints.maxHeight * devicePixelRatio)
|
|
||||||
.round(),
|
|
||||||
policy: ResizeImagePolicy.fit,
|
|
||||||
),
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Material(
|
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,59 +21,10 @@ class PostItem extends StatelessWidget {
|
|||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
_PostContentHeader(data: data).padding(horizontal: 12, vertical: 8),
|
_PostContentHeader(data: data),
|
||||||
_PostContentBody(data: data.body).padding(horizontal: 16, bottom: 6),
|
_PostContentBody(data: data.body).padding(horizontal: 16, bottom: 6),
|
||||||
if (data.preload?.attachments?.isNotEmpty ?? true)
|
if (data.preload?.attachments?.isNotEmpty ?? true)
|
||||||
AttachmentList(data: data.preload!.attachments!, bordered: true),
|
AttachmentList(data: data.preload!.attachments!, bordered: true),
|
||||||
_PostBottomAction(data: data)
|
|
||||||
.padding(left: 20, right: 26, top: 8, bottom: 2),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _PostBottomAction extends StatelessWidget {
|
|
||||||
final SnPost data;
|
|
||||||
const _PostBottomAction({required this.data});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final iconColor = Theme.of(context).colorScheme.onSurface.withAlpha(
|
|
||||||
(255 * 0.8).round(),
|
|
||||||
);
|
|
||||||
return Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
InkWell(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Icon(Symbols.add_reaction, size: 20, color: iconColor),
|
|
||||||
const Gap(8),
|
|
||||||
Text('postReact').tr(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
onTap: () {},
|
|
||||||
),
|
|
||||||
const Gap(16),
|
|
||||||
InkWell(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Icon(Symbols.comment, size: 20, color: iconColor),
|
|
||||||
const Gap(8),
|
|
||||||
Text('postComments').plural(data.metric.replyCount),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
onTap: () {},
|
|
||||||
),
|
|
||||||
].expand((ele) => [ele, const Gap(8)]).toList()
|
|
||||||
..removeLast(),
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
child: Icon(Symbols.share, size: 20, color: iconColor),
|
|
||||||
onTap: () {},
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -188,7 +139,7 @@ class _PostContentHeader extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
).padding(horizontal: 12, vertical: 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "4.10.1"
|
version: "4.10.1"
|
||||||
collection:
|
collection:
|
||||||
dependency: "direct main"
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: collection
|
name: collection
|
||||||
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
|
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
|
||||||
@ -987,7 +987,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.0"
|
version: "1.9.0"
|
||||||
path_provider:
|
path_provider:
|
||||||
dependency: "direct main"
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider
|
name: path_provider
|
||||||
sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
|
sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
|
||||||
|
@ -71,8 +71,6 @@ dependencies:
|
|||||||
uuid: ^4.5.1
|
uuid: ^4.5.1
|
||||||
photo_view: ^0.15.0
|
photo_view: ^0.15.0
|
||||||
shared_preferences: ^2.3.3
|
shared_preferences: ^2.3.3
|
||||||
path_provider: ^2.1.5
|
|
||||||
collection: ^1.19.0
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user