Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
c5258cb9ca | |||
47c535910d | |||
66f2f33394 | |||
f5fbe1f483 | |||
fcf4dc7a2d | |||
43b7059957 |
@ -468,5 +468,14 @@
|
|||||||
"all": "All",
|
"all": "All",
|
||||||
"unablePreview": "Unable to preview",
|
"unablePreview": "Unable to preview",
|
||||||
"dashboardNav": "Dash",
|
"dashboardNav": "Dash",
|
||||||
"accountNav": "You"
|
"accountNav": "You",
|
||||||
|
"performance": "Performance",
|
||||||
|
"animatedMessageList": "Non-animated message list",
|
||||||
|
"animatedMessageListDesc": "Remove animation effects in message list, to reduce cause lag",
|
||||||
|
"theme": "Theme",
|
||||||
|
"globalTheme": "Global theme",
|
||||||
|
"agedTheme": "Old school style theme",
|
||||||
|
"agedThemeDesc": "Downgrade the global theme to Material Design 2. Unexpected issues may occur. For experimental use only.",
|
||||||
|
"appBackgroundImage": "Global background image",
|
||||||
|
"appBackgroundImageDesc": "The global background image will be displayed on all pages"
|
||||||
}
|
}
|
||||||
|
@ -266,7 +266,7 @@
|
|||||||
"channelMembersAddHint": "到 @channel",
|
"channelMembersAddHint": "到 @channel",
|
||||||
"channelType": "频道类型",
|
"channelType": "频道类型",
|
||||||
"channelTypeCommon": "普通频道",
|
"channelTypeCommon": "普通频道",
|
||||||
"channelTypeDirect": "私信聊天",
|
"channelTypeDirect": "私信",
|
||||||
"channelAdjust": "调整频道",
|
"channelAdjust": "调整频道",
|
||||||
"channelDetail": "频道详情",
|
"channelDetail": "频道详情",
|
||||||
"channelSettings": "频道设置",
|
"channelSettings": "频道设置",
|
||||||
@ -464,5 +464,14 @@
|
|||||||
"all": "全部",
|
"all": "全部",
|
||||||
"unablePreview": "无法预览",
|
"unablePreview": "无法预览",
|
||||||
"dashboardNav": "仪表盘",
|
"dashboardNav": "仪表盘",
|
||||||
"accountNav": "您"
|
"accountNav": "您",
|
||||||
|
"performance": "性能",
|
||||||
|
"animatedMessageList": "无动画消息列表",
|
||||||
|
"animatedMessageListDesc": "在消息列表中禁用动画效果",
|
||||||
|
"theme": "主题",
|
||||||
|
"globalTheme": "全局应用主题",
|
||||||
|
"agedTheme": "过时主题",
|
||||||
|
"agedThemeDesc": "将全局主题降级为 Material Design 2,可能发生意料之外的问题,仅供实验使用",
|
||||||
|
"appBackgroundImage": "全局背景图片",
|
||||||
|
"appBackgroundImageDesc": "全局背景图片将会在所有页面中展示"
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import 'package:solian/providers/relation.dart';
|
|||||||
import 'package:solian/providers/theme_switcher.dart';
|
import 'package:solian/providers/theme_switcher.dart';
|
||||||
import 'package:solian/providers/websocket.dart';
|
import 'package:solian/providers/websocket.dart';
|
||||||
import 'package:solian/services.dart';
|
import 'package:solian/services.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
import 'package:solian/widgets/sized_container.dart';
|
import 'package:solian/widgets/sized_container.dart';
|
||||||
import 'package:flutter_app_update/flutter_app_update.dart';
|
import 'package:flutter_app_update/flutter_app_update.dart';
|
||||||
import 'package:version/version.dart';
|
import 'package:version/version.dart';
|
||||||
@ -255,8 +256,7 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (_isBusy || _isErrored) {
|
if (_isBusy || _isErrored) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
child: Material(
|
child: RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
50
lib/models/theme.dart
Normal file
50
lib/models/theme.dart
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
|
part 'theme.g.dart';
|
||||||
|
|
||||||
|
@JsonSerializable(converters: [ColorConverter()])
|
||||||
|
class SolianThemeData {
|
||||||
|
String id;
|
||||||
|
Color seedColor;
|
||||||
|
String? fontFamily;
|
||||||
|
List<String>? fontFamilyFallback;
|
||||||
|
|
||||||
|
SolianThemeData({
|
||||||
|
required this.id,
|
||||||
|
required this.seedColor,
|
||||||
|
this.fontFamily,
|
||||||
|
this.fontFamilyFallback,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory SolianThemeData.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SolianThemeDataFromJson(json);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => _$SolianThemeDataToJson(this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => id.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (other is SolianThemeData) {
|
||||||
|
return id == other.id;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ColorConverter extends JsonConverter<Color, int> {
|
||||||
|
const ColorConverter();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color fromJson(int json) {
|
||||||
|
return Color(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int toJson(Color object) {
|
||||||
|
return object.value;
|
||||||
|
}
|
||||||
|
}
|
26
lib/models/theme.g.dart
Normal file
26
lib/models/theme.g.dart
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'theme.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
SolianThemeData _$SolianThemeDataFromJson(Map<String, dynamic> json) =>
|
||||||
|
SolianThemeData(
|
||||||
|
id: json['id'] as String,
|
||||||
|
seedColor:
|
||||||
|
const ColorConverter().fromJson((json['seed_color'] as num).toInt()),
|
||||||
|
fontFamily: json['font_family'] as String?,
|
||||||
|
fontFamilyFallback: (json['font_family_fallback'] as List<dynamic>?)
|
||||||
|
?.map((e) => e as String)
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$SolianThemeDataToJson(SolianThemeData instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'id': instance.id,
|
||||||
|
'seed_color': const ColorConverter().toJson(instance.seedColor),
|
||||||
|
'font_family': instance.fontFamily,
|
||||||
|
'font_family_fallback': instance.fontFamilyFallback,
|
||||||
|
};
|
@ -1,5 +1,8 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
import 'package:solian/models/theme.dart';
|
||||||
import 'package:solian/theme.dart';
|
import 'package:solian/theme.dart';
|
||||||
|
|
||||||
class ThemeSwitcher extends ChangeNotifier {
|
class ThemeSwitcher extends ChangeNotifier {
|
||||||
@ -13,11 +16,21 @@ class ThemeSwitcher extends ChangeNotifier {
|
|||||||
|
|
||||||
Future<void> restoreTheme() async {
|
Future<void> restoreTheme() async {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
if (prefs.containsKey('global_theme_color')) {
|
if (prefs.containsKey('global_theme')) {
|
||||||
final value = prefs.getInt('global_theme_color')!;
|
final value = SolianThemeData.fromJson(
|
||||||
final color = Color(value);
|
jsonDecode(prefs.getString('global_theme')!),
|
||||||
lightThemeData = AppTheme.build(Brightness.light, seedColor: color);
|
);
|
||||||
darkThemeData = AppTheme.build(Brightness.dark, seedColor: color);
|
final agedTheme = prefs.getBool('aged_theme');
|
||||||
|
lightThemeData = AppTheme.buildFromData(
|
||||||
|
Brightness.light,
|
||||||
|
value,
|
||||||
|
useMaterial3: agedTheme == null ? true : !agedTheme,
|
||||||
|
);
|
||||||
|
darkThemeData = AppTheme.buildFromData(
|
||||||
|
Brightness.dark,
|
||||||
|
value,
|
||||||
|
useMaterial3: agedTheme == null ? true : !agedTheme,
|
||||||
|
);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -27,4 +40,25 @@ class ThemeSwitcher extends ChangeNotifier {
|
|||||||
darkThemeData = dark;
|
darkThemeData = dark;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> setThemeData(SolianThemeData? data) async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
if (data == null) {
|
||||||
|
prefs.remove('global_theme');
|
||||||
|
} else {
|
||||||
|
prefs.setString(
|
||||||
|
'global_theme',
|
||||||
|
jsonEncode(data.toJson()),
|
||||||
|
);
|
||||||
|
lightThemeData = AppTheme.buildFromData(Brightness.light, data);
|
||||||
|
darkThemeData = AppTheme.buildFromData(Brightness.dark, data);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setAgedTheme(bool enabled) async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
prefs.setBool('aged_theme', enabled);
|
||||||
|
await restoreTheme();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import 'package:get/get.dart';
|
|||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
import 'package:solian/widgets/sized_container.dart';
|
import 'package:solian/widgets/sized_container.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
|
||||||
@ -15,8 +16,7 @@ class AboutScreen extends StatelessWidget {
|
|||||||
const denseButtonStyle =
|
const denseButtonStyle =
|
||||||
ButtonStyle(visualDensity: VisualDensity(vertical: -4));
|
ButtonStyle(visualDensity: VisualDensity(vertical: -4));
|
||||||
|
|
||||||
return Material(
|
return RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: Column(
|
child: Column(
|
||||||
|
@ -7,6 +7,7 @@ import 'package:solian/providers/account_status.dart';
|
|||||||
import 'package:solian/providers/relation.dart';
|
import 'package:solian/providers/relation.dart';
|
||||||
import 'package:solian/router.dart';
|
import 'package:solian/router.dart';
|
||||||
import 'package:solian/widgets/account/account_heading.dart';
|
import 'package:solian/widgets/account/account_heading.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
import 'package:solian/widgets/sized_container.dart';
|
import 'package:solian/widgets/sized_container.dart';
|
||||||
import 'package:badges/badges.dart' as badges;
|
import 'package:badges/badges.dart' as badges;
|
||||||
|
|
||||||
@ -49,8 +50,7 @@ class _AccountScreenState extends State<AccountScreen> {
|
|||||||
|
|
||||||
final AuthProvider auth = Get.find();
|
final AuthProvider auth = Get.find();
|
||||||
|
|
||||||
return Material(
|
return RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
child: Obx(() {
|
child: Obx(() {
|
||||||
if (auth.isAuthorized.isFalse) {
|
if (auth.isAuthorized.isFalse) {
|
||||||
|
@ -6,6 +6,7 @@ import 'package:solian/models/relations.dart';
|
|||||||
import 'package:solian/providers/relation.dart';
|
import 'package:solian/providers/relation.dart';
|
||||||
import 'package:solian/theme.dart';
|
import 'package:solian/theme.dart';
|
||||||
import 'package:solian/widgets/account/relative_list.dart';
|
import 'package:solian/widgets/account/relative_list.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
|
|
||||||
class FriendScreen extends StatefulWidget {
|
class FriendScreen extends StatefulWidget {
|
||||||
const FriendScreen({super.key});
|
const FriendScreen({super.key});
|
||||||
@ -117,8 +118,7 @@ class _FriendScreenState extends State<FriendScreen>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Material(
|
return RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
|
@ -6,6 +6,7 @@ import 'package:google_fonts/google_fonts.dart';
|
|||||||
import 'package:solian/exceptions/request.dart';
|
import 'package:solian/exceptions/request.dart';
|
||||||
import 'package:solian/exts.dart';
|
import 'package:solian/exts.dart';
|
||||||
import 'package:solian/providers/auth.dart';
|
import 'package:solian/providers/auth.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
|
|
||||||
class NotificationPreferencesScreen extends StatefulWidget {
|
class NotificationPreferencesScreen extends StatefulWidget {
|
||||||
const NotificationPreferencesScreen({super.key});
|
const NotificationPreferencesScreen({super.key});
|
||||||
@ -74,8 +75,7 @@ class _NotificationPreferencesScreenState
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Material(
|
return RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
if (_isBusy) const LinearProgressIndicator().animate().scaleX(),
|
if (_isBusy) const LinearProgressIndicator().animate().scaleX(),
|
||||||
|
@ -12,6 +12,7 @@ import 'package:solian/providers/auth.dart';
|
|||||||
import 'package:solian/providers/content/attachment.dart';
|
import 'package:solian/providers/content/attachment.dart';
|
||||||
import 'package:solian/services.dart';
|
import 'package:solian/services.dart';
|
||||||
import 'package:solian/widgets/account/account_avatar.dart';
|
import 'package:solian/widgets/account/account_avatar.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
|
|
||||||
class PersonalizeScreen extends StatefulWidget {
|
class PersonalizeScreen extends StatefulWidget {
|
||||||
const PersonalizeScreen({super.key});
|
const PersonalizeScreen({super.key});
|
||||||
@ -186,8 +187,7 @@ class _PersonalizeScreenState extends State<PersonalizeScreen> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
const double padding = 32;
|
const double padding = 32;
|
||||||
|
|
||||||
return Material(
|
return RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: ListView(
|
child: ListView(
|
||||||
children: [
|
children: [
|
||||||
if (_isBusy) const LinearProgressIndicator().animate().scaleX(),
|
if (_isBusy) const LinearProgressIndicator().animate().scaleX(),
|
||||||
|
@ -28,6 +28,7 @@ import 'package:solian/widgets/daily_sign/history_chart.dart';
|
|||||||
import 'package:solian/widgets/posts/post_list.dart';
|
import 'package:solian/widgets/posts/post_list.dart';
|
||||||
import 'package:solian/widgets/posts/post_warped_list.dart';
|
import 'package:solian/widgets/posts/post_warped_list.dart';
|
||||||
import 'package:solian/widgets/reports/abuse_report.dart';
|
import 'package:solian/widgets/reports/abuse_report.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
import 'package:solian/widgets/sized_container.dart';
|
import 'package:solian/widgets/sized_container.dart';
|
||||||
|
|
||||||
class AccountProfilePage extends StatefulWidget {
|
class AccountProfilePage extends StatefulWidget {
|
||||||
@ -233,8 +234,7 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
|
|||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
}
|
}
|
||||||
|
|
||||||
return Material(
|
return RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: DefaultTabController(
|
child: DefaultTabController(
|
||||||
length: 3,
|
length: 3,
|
||||||
child: NestedScrollView(
|
child: NestedScrollView(
|
||||||
|
@ -11,6 +11,7 @@ import 'package:solian/providers/content/realm.dart';
|
|||||||
import 'package:solian/providers/relation.dart';
|
import 'package:solian/providers/relation.dart';
|
||||||
import 'package:solian/providers/websocket.dart';
|
import 'package:solian/providers/websocket.dart';
|
||||||
import 'package:solian/services.dart';
|
import 'package:solian/services.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
import 'package:solian/widgets/sized_container.dart';
|
import 'package:solian/widgets/sized_container.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
|
||||||
@ -216,8 +217,7 @@ class _SignInScreenState extends State<SignInScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Material(
|
return RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: CenteredContainer(
|
child: CenteredContainer(
|
||||||
maxWidth: 360,
|
maxWidth: 360,
|
||||||
child: PageTransitionSwitcher(
|
child: PageTransitionSwitcher(
|
||||||
|
@ -3,6 +3,7 @@ import 'package:gap/gap.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:solian/exts.dart';
|
import 'package:solian/exts.dart';
|
||||||
import 'package:solian/services.dart';
|
import 'package:solian/services.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
import 'package:solian/widgets/sized_container.dart';
|
import 'package:solian/widgets/sized_container.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
|
||||||
@ -65,8 +66,7 @@ class _SignUpScreenState extends State<SignUpScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Material(
|
return RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: CenteredContainer(
|
child: CenteredContainer(
|
||||||
maxWidth: 360,
|
maxWidth: 360,
|
||||||
child: ListView(
|
child: ListView(
|
||||||
|
@ -11,6 +11,7 @@ import 'package:solian/widgets/app_bar_leading.dart';
|
|||||||
import 'package:solian/widgets/chat/call/call_controls.dart';
|
import 'package:solian/widgets/chat/call/call_controls.dart';
|
||||||
import 'package:solian/widgets/chat/call/call_participant.dart';
|
import 'package:solian/widgets/chat/call/call_participant.dart';
|
||||||
import 'package:livekit_client/livekit_client.dart' as livekit;
|
import 'package:livekit_client/livekit_client.dart' as livekit;
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
|
|
||||||
class CallScreen extends StatefulWidget {
|
class CallScreen extends StatefulWidget {
|
||||||
final bool hideAppBar;
|
final bool hideAppBar;
|
||||||
@ -197,8 +198,7 @@ class _CallScreenState extends State<CallScreen> with TickerProviderStateMixin {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final ChatCallProvider ctrl = Get.find();
|
final ChatCallProvider ctrl = Get.find();
|
||||||
|
|
||||||
return Material(
|
return RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: widget.hideAppBar
|
appBar: widget.hideAppBar
|
||||||
? null
|
? null
|
||||||
|
@ -3,6 +3,7 @@ import 'dart:ui';
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:solian/controllers/chat_events_controller.dart';
|
import 'package:solian/controllers/chat_events_controller.dart';
|
||||||
import 'package:solian/exts.dart';
|
import 'package:solian/exts.dart';
|
||||||
import 'package:solian/models/call.dart';
|
import 'package:solian/models/call.dart';
|
||||||
@ -25,6 +26,7 @@ import 'package:solian/widgets/chat/chat_event_list.dart';
|
|||||||
import 'package:solian/widgets/chat/chat_message_input.dart';
|
import 'package:solian/widgets/chat/chat_message_input.dart';
|
||||||
import 'package:solian/widgets/chat/chat_typing_indicator.dart';
|
import 'package:solian/widgets/chat/chat_typing_indicator.dart';
|
||||||
import 'package:solian/widgets/current_state_action.dart';
|
import 'package:solian/widgets/current_state_action.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
|
|
||||||
class ChannelChatScreen extends StatefulWidget {
|
class ChannelChatScreen extends StatefulWidget {
|
||||||
final String alias;
|
final String alias;
|
||||||
@ -179,6 +181,8 @@ class _ChannelChatScreenState extends State<ChannelChatScreen>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
late SharedPreferences _prefs;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@ -189,11 +193,14 @@ class _ChannelChatScreenState extends State<ChannelChatScreen>
|
|||||||
_chatController = ChatEventController();
|
_chatController = ChatEventController();
|
||||||
_chatController.initialize();
|
_chatController.initialize();
|
||||||
|
|
||||||
|
SharedPreferences.getInstance().then((inst) {
|
||||||
|
_prefs = inst;
|
||||||
_getOngoingCall();
|
_getOngoingCall();
|
||||||
_getChannel().then((_) {
|
_getChannel().then((_) {
|
||||||
_chatController.getInitialEvents(_channel!, widget.realm);
|
_chatController.getInitialEvents(_channel!, widget.realm);
|
||||||
_listenMessages();
|
_listenMessages();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -211,7 +218,8 @@ class _ChannelChatScreenState extends State<ChannelChatScreen>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return RootContainer(
|
||||||
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: AppBarLeadingButton.adaptive(context),
|
leading: AppBarLeadingButton.adaptive(context),
|
||||||
title: AppBarTitle(title),
|
title: AppBarTitle(title),
|
||||||
@ -247,7 +255,8 @@ class _ChannelChatScreenState extends State<ChannelChatScreen>
|
|||||||
.then((value) {
|
.then((value) {
|
||||||
if (value == false) AppRouter.instance.pop();
|
if (value == false) AppRouter.instance.pop();
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
final resp = Channel.fromJson(value as Map<String, dynamic>);
|
final resp =
|
||||||
|
Channel.fromJson(value as Map<String, dynamic>);
|
||||||
_getChannel(alias: resp.alias);
|
_getChannel(alias: resp.alias);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -283,6 +292,9 @@ class _ChannelChatScreenState extends State<ChannelChatScreen>
|
|||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ChatEventList(
|
child: ChatEventList(
|
||||||
|
noAnimated:
|
||||||
|
_prefs.getBool('non_animated_message_list') ??
|
||||||
|
false,
|
||||||
scope: widget.realm,
|
scope: widget.realm,
|
||||||
channel: _channel!,
|
channel: _channel!,
|
||||||
chatController: _chatController,
|
chatController: _chatController,
|
||||||
@ -348,6 +360,7 @@ class _ChannelChatScreenState extends State<ChannelChatScreen>
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ import 'package:solian/providers/content/channel.dart';
|
|||||||
import 'package:solian/router.dart';
|
import 'package:solian/router.dart';
|
||||||
import 'package:solian/theme.dart';
|
import 'package:solian/theme.dart';
|
||||||
import 'package:solian/widgets/app_bar_title.dart';
|
import 'package:solian/widgets/app_bar_title.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
class ChannelOrganizeArguments {
|
class ChannelOrganizeArguments {
|
||||||
@ -114,8 +115,7 @@ class _ChannelOrganizeScreenState extends State<ChannelOrganizeScreen> {
|
|||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
return Material(
|
return RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: AppBarTitle('channelOrganizing'.tr),
|
title: AppBarTitle('channelOrganizing'.tr),
|
||||||
|
@ -19,6 +19,7 @@ import 'package:solian/widgets/app_bar_title.dart';
|
|||||||
import 'package:solian/widgets/channel/channel_list.dart';
|
import 'package:solian/widgets/channel/channel_list.dart';
|
||||||
import 'package:solian/widgets/chat/call/chat_call_indicator.dart';
|
import 'package:solian/widgets/chat/call/chat_call_indicator.dart';
|
||||||
import 'package:solian/widgets/current_state_action.dart';
|
import 'package:solian/widgets/current_state_action.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
import 'package:solian/widgets/sidebar/empty_placeholder.dart';
|
import 'package:solian/widgets/sidebar/empty_placeholder.dart';
|
||||||
|
|
||||||
class ChatScreen extends StatelessWidget {
|
class ChatScreen extends StatelessWidget {
|
||||||
@ -26,9 +27,8 @@ class ChatScreen extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Material(
|
return const RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
child: ChatList(),
|
||||||
child: const ChatList(),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -40,8 +40,7 @@ class ChatListShell extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Material(
|
return RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
@ -141,6 +140,7 @@ class _ChatListState extends State<ChatList> {
|
|||||||
return Obx(
|
return Obx(
|
||||||
() => DefaultTabController(
|
() => DefaultTabController(
|
||||||
length: 2 + realms.availableRealms.length,
|
length: 2 + realms.availableRealms.length,
|
||||||
|
child: RootContainer(
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: Obx(() {
|
leading: Obx(() {
|
||||||
@ -166,7 +166,8 @@ class _ChatListState extends State<ChatList> {
|
|||||||
child: ListTile(
|
child: ListTile(
|
||||||
title: Text('channelOrganizeCommon'.tr),
|
title: Text('channelOrganizeCommon'.tr),
|
||||||
leading: const Icon(Icons.tag),
|
leading: const Icon(Icons.tag),
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 8),
|
contentPadding:
|
||||||
|
const EdgeInsets.symmetric(horizontal: 8),
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
AppRouter.instance.pushNamed('channelOrganizing').then(
|
AppRouter.instance.pushNamed('channelOrganizing').then(
|
||||||
@ -185,7 +186,8 @@ class _ChatListState extends State<ChatList> {
|
|||||||
FontAwesomeIcons.userGroup,
|
FontAwesomeIcons.userGroup,
|
||||||
size: 16,
|
size: 16,
|
||||||
),
|
),
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 8),
|
contentPadding:
|
||||||
|
const EdgeInsets.symmetric(horizontal: 8),
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
final ChannelProvider channels = Get.find();
|
final ChannelProvider channels = Get.find();
|
||||||
@ -217,7 +219,8 @@ class _ChatListState extends State<ChatList> {
|
|||||||
children: [
|
children: [
|
||||||
CircleAvatar(
|
CircleAvatar(
|
||||||
radius: 14,
|
radius: 14,
|
||||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
backgroundColor:
|
||||||
|
Theme.of(context).colorScheme.primary,
|
||||||
child: const Icon(
|
child: const Icon(
|
||||||
Icons.forum,
|
Icons.forum,
|
||||||
size: 16,
|
size: 16,
|
||||||
@ -318,6 +321,7 @@ class _ChatListState extends State<ChatList> {
|
|||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -354,7 +354,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.arrow_forward),
|
icon: const Icon(Icons.arrow_forward),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
AppRouter.instance.goNamed('feed');
|
AppRouter.instance.goNamed('explore');
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -15,6 +15,7 @@ import 'package:solian/widgets/app_bar_leading.dart';
|
|||||||
import 'package:solian/widgets/navigation/realm_switcher.dart';
|
import 'package:solian/widgets/navigation/realm_switcher.dart';
|
||||||
import 'package:solian/widgets/posts/post_shuffle_swiper.dart';
|
import 'package:solian/widgets/posts/post_shuffle_swiper.dart';
|
||||||
import 'package:solian/widgets/posts/post_warped_list.dart';
|
import 'package:solian/widgets/posts/post_warped_list.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
|
|
||||||
class ExploreScreen extends StatefulWidget {
|
class ExploreScreen extends StatefulWidget {
|
||||||
const ExploreScreen({super.key});
|
const ExploreScreen({super.key});
|
||||||
@ -56,8 +57,7 @@ class _ExploreScreenState extends State<ExploreScreen>
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final AuthProvider auth = Get.find();
|
final AuthProvider auth = Get.find();
|
||||||
|
|
||||||
return Material(
|
return RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
child: const Icon(Icons.add),
|
child: const Icon(Icons.add),
|
||||||
|
@ -9,6 +9,7 @@ import 'package:solian/widgets/app_bar_leading.dart';
|
|||||||
import 'package:solian/widgets/app_bar_title.dart';
|
import 'package:solian/widgets/app_bar_title.dart';
|
||||||
import 'package:solian/widgets/posts/post_action.dart';
|
import 'package:solian/widgets/posts/post_action.dart';
|
||||||
import 'package:solian/widgets/posts/post_owned_list.dart';
|
import 'package:solian/widgets/posts/post_owned_list.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
|
|
||||||
class DraftBoxScreen extends StatefulWidget {
|
class DraftBoxScreen extends StatefulWidget {
|
||||||
const DraftBoxScreen({super.key});
|
const DraftBoxScreen({super.key});
|
||||||
@ -54,8 +55,7 @@ class _DraftBoxScreenState extends State<DraftBoxScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Material(
|
return RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: AppBarLeadingButton.adaptive(context),
|
leading: AppBarLeadingButton.adaptive(context),
|
||||||
|
@ -6,6 +6,7 @@ import 'package:solian/providers/content/posts.dart';
|
|||||||
import 'package:solian/providers/last_read.dart';
|
import 'package:solian/providers/last_read.dart';
|
||||||
import 'package:solian/widgets/posts/post_item.dart';
|
import 'package:solian/widgets/posts/post_item.dart';
|
||||||
import 'package:solian/widgets/posts/post_replies.dart';
|
import 'package:solian/widgets/posts/post_replies.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
|
|
||||||
class PostDetailScreen extends StatefulWidget {
|
class PostDetailScreen extends StatefulWidget {
|
||||||
final String id;
|
final String id;
|
||||||
@ -47,8 +48,7 @@ class _PostDetailScreenState extends State<PostDetailScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Material(
|
return RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: FutureBuilder(
|
child: FutureBuilder(
|
||||||
future: getDetail(),
|
future: getDetail(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
@ -19,6 +19,7 @@ import 'package:solian/widgets/app_bar_title.dart';
|
|||||||
import 'package:solian/widgets/markdown_text_content.dart';
|
import 'package:solian/widgets/markdown_text_content.dart';
|
||||||
import 'package:solian/widgets/posts/post_item.dart';
|
import 'package:solian/widgets/posts/post_item.dart';
|
||||||
import 'package:badges/badges.dart' as badges;
|
import 'package:badges/badges.dart' as badges;
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
|
|
||||||
class PostPublishArguments {
|
class PostPublishArguments {
|
||||||
final Post? edit;
|
final Post? edit;
|
||||||
@ -151,8 +152,7 @@ class _PostPublishScreenState extends State<PostPublishScreen> {
|
|||||||
)
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
return Material(
|
return RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: AppBarLeadingButton.adaptive(context),
|
leading: AppBarLeadingButton.adaptive(context),
|
||||||
|
@ -15,6 +15,7 @@ import 'package:solian/widgets/app_bar_leading.dart';
|
|||||||
import 'package:solian/widgets/app_bar_title.dart';
|
import 'package:solian/widgets/app_bar_title.dart';
|
||||||
import 'package:solian/widgets/auto_cache_image.dart';
|
import 'package:solian/widgets/auto_cache_image.dart';
|
||||||
import 'package:solian/widgets/current_state_action.dart';
|
import 'package:solian/widgets/current_state_action.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
import 'package:solian/widgets/sized_container.dart';
|
import 'package:solian/widgets/sized_container.dart';
|
||||||
|
|
||||||
class RealmListScreen extends StatefulWidget {
|
class RealmListScreen extends StatefulWidget {
|
||||||
@ -58,8 +59,7 @@ class _RealmListScreenState extends State<RealmListScreen> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final AuthProvider auth = Get.find();
|
final AuthProvider auth = Get.find();
|
||||||
|
|
||||||
return Material(
|
return RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: AppBarLeadingButton.adaptive(context),
|
leading: AppBarLeadingButton.adaptive(context),
|
||||||
|
@ -7,6 +7,7 @@ import 'package:solian/router.dart';
|
|||||||
import 'package:solian/screens/realms/realm_organize.dart';
|
import 'package:solian/screens/realms/realm_organize.dart';
|
||||||
import 'package:solian/widgets/realms/realm_deletion.dart';
|
import 'package:solian/widgets/realms/realm_deletion.dart';
|
||||||
import 'package:solian/widgets/realms/realm_member.dart';
|
import 'package:solian/widgets/realms/realm_member.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
|
|
||||||
class RealmDetailScreen extends StatefulWidget {
|
class RealmDetailScreen extends StatefulWidget {
|
||||||
final String alias;
|
final String alias;
|
||||||
@ -86,7 +87,8 @@ class _RealmDetailScreenState extends State<RealmDetailScreen> {
|
|||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
return Column(
|
return RootContainer(
|
||||||
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
@ -141,6 +143,7 @@ class _RealmDetailScreenState extends State<RealmDetailScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import 'package:solian/router.dart';
|
|||||||
import 'package:solian/theme.dart';
|
import 'package:solian/theme.dart';
|
||||||
import 'package:solian/widgets/app_bar_leading.dart';
|
import 'package:solian/widgets/app_bar_leading.dart';
|
||||||
import 'package:solian/widgets/app_bar_title.dart';
|
import 'package:solian/widgets/app_bar_title.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
class RealmOrganizeArguments {
|
class RealmOrganizeArguments {
|
||||||
@ -189,8 +190,7 @@ class _RealmOrganizeScreenState extends State<RealmOrganizeScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Material(
|
return RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: AppBarLeadingButton.adaptive(context),
|
leading: AppBarLeadingButton.adaptive(context),
|
||||||
|
@ -16,6 +16,7 @@ import 'package:solian/theme.dart';
|
|||||||
import 'package:solian/widgets/app_bar_leading.dart';
|
import 'package:solian/widgets/app_bar_leading.dart';
|
||||||
import 'package:solian/widgets/channel/channel_list.dart';
|
import 'package:solian/widgets/channel/channel_list.dart';
|
||||||
import 'package:solian/widgets/posts/post_list.dart';
|
import 'package:solian/widgets/posts/post_list.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
|
|
||||||
class RealmViewScreen extends StatefulWidget {
|
class RealmViewScreen extends StatefulWidget {
|
||||||
final String alias;
|
final String alias;
|
||||||
@ -86,8 +87,7 @@ class _RealmViewScreenState extends State<RealmViewScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Material(
|
return RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: DefaultTabController(
|
child: DefaultTabController(
|
||||||
length: 2,
|
length: 2,
|
||||||
child: NestedScrollView(
|
child: NestedScrollView(
|
||||||
|
@ -1,17 +1,25 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:dropdown_button2/dropdown_button2.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:gap/gap.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:in_app_review/in_app_review.dart';
|
import 'package:in_app_review/in_app_review.dart';
|
||||||
|
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:solian/exceptions/request.dart';
|
import 'package:solian/exceptions/request.dart';
|
||||||
import 'package:solian/exts.dart';
|
import 'package:solian/exts.dart';
|
||||||
|
import 'package:solian/models/theme.dart';
|
||||||
import 'package:solian/platform.dart';
|
import 'package:solian/platform.dart';
|
||||||
import 'package:solian/providers/auth.dart';
|
import 'package:solian/providers/auth.dart';
|
||||||
import 'package:solian/providers/database/database.dart';
|
import 'package:solian/providers/database/database.dart';
|
||||||
import 'package:solian/providers/theme_switcher.dart';
|
import 'package:solian/providers/theme_switcher.dart';
|
||||||
import 'package:solian/router.dart';
|
import 'package:solian/router.dart';
|
||||||
import 'package:solian/theme.dart';
|
|
||||||
import 'package:solian/widgets/reports/abuse_report.dart';
|
import 'package:solian/widgets/reports/abuse_report.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
|
|
||||||
class SettingScreen extends StatefulWidget {
|
class SettingScreen extends StatefulWidget {
|
||||||
const SettingScreen({super.key});
|
const SettingScreen({super.key});
|
||||||
@ -22,6 +30,7 @@ class SettingScreen extends StatefulWidget {
|
|||||||
|
|
||||||
class _SettingScreenState extends State<SettingScreen> {
|
class _SettingScreenState extends State<SettingScreen> {
|
||||||
SharedPreferences? _prefs;
|
SharedPreferences? _prefs;
|
||||||
|
String _docBasepath = '/';
|
||||||
|
|
||||||
Widget _buildCaptionHeader(String title) {
|
Widget _buildCaptionHeader(String title) {
|
||||||
return Container(
|
return Container(
|
||||||
@ -32,39 +41,38 @@ class _SettingScreenState extends State<SettingScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildThemeColorButton(String label, Color color) {
|
static final List<SolianThemeData> _presentTheme = [
|
||||||
return IconButton(
|
SolianThemeData(
|
||||||
icon: Icon(Icons.circle, color: color),
|
id: 'themeColorRed',
|
||||||
tooltip: label,
|
seedColor: const Color.fromRGBO(154, 98, 91, 1),
|
||||||
onPressed: () {
|
|
||||||
context.read<ThemeSwitcher>().setTheme(
|
|
||||||
AppTheme.build(
|
|
||||||
Brightness.light,
|
|
||||||
seedColor: color,
|
|
||||||
),
|
),
|
||||||
AppTheme.build(
|
SolianThemeData(
|
||||||
Brightness.dark,
|
id: 'themeColorBlue',
|
||||||
seedColor: color,
|
seedColor: const Color.fromRGBO(103, 96, 193, 1),
|
||||||
|
),
|
||||||
|
SolianThemeData(
|
||||||
|
id: 'themeColorMiku',
|
||||||
|
seedColor: const Color.fromRGBO(56, 120, 126, 1),
|
||||||
|
),
|
||||||
|
SolianThemeData(
|
||||||
|
id: 'themeColorKagamine',
|
||||||
|
seedColor: const Color.fromRGBO(244, 183, 63, 1),
|
||||||
|
),
|
||||||
|
SolianThemeData(
|
||||||
|
id: 'themeColorLuka',
|
||||||
|
seedColor: const Color.fromRGBO(243, 174, 218, 1),
|
||||||
),
|
),
|
||||||
);
|
|
||||||
_prefs?.setInt('global_theme_color', color.value);
|
|
||||||
context.clearSnackbar();
|
|
||||||
context.showSnackbar('themeColorApplied'.tr);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static final List<(String, Color)> _presentTheme = [
|
|
||||||
('themeColorRed', const Color.fromRGBO(154, 98, 91, 1)),
|
|
||||||
('themeColorBlue', const Color.fromRGBO(103, 96, 193, 1)),
|
|
||||||
('themeColorMiku', const Color.fromRGBO(56, 120, 126, 1)),
|
|
||||||
('themeColorKagamine', const Color.fromRGBO(244, 183, 63, 1)),
|
|
||||||
('themeColorLuka', const Color.fromRGBO(243, 174, 218, 1)),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
getApplicationDocumentsDirectory().then((dir) {
|
||||||
|
_docBasepath = dir.path;
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
});
|
||||||
SharedPreferences.getInstance().then((inst) {
|
SharedPreferences.getInstance().then((inst) {
|
||||||
_prefs = inst;
|
_prefs = inst;
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
@ -75,19 +83,100 @@ class _SettingScreenState extends State<SettingScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Material(
|
return RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: ListView(
|
child: ListView(
|
||||||
children: [
|
children: [
|
||||||
_buildCaptionHeader('themeColor'.tr),
|
_buildCaptionHeader('theme'.tr),
|
||||||
SizedBox(
|
ListTile(
|
||||||
height: 56,
|
leading: const Icon(Icons.palette),
|
||||||
child: ListView(
|
contentPadding: const EdgeInsets.symmetric(horizontal: 22),
|
||||||
scrollDirection: Axis.horizontal,
|
title: Text('globalTheme'.tr),
|
||||||
children: _presentTheme
|
trailing: DropdownButtonHideUnderline(
|
||||||
.map((x) => _buildThemeColorButton(x.$1, x.$2))
|
child: DropdownButton2<SolianThemeData>(
|
||||||
|
isExpanded: true,
|
||||||
|
hint: Text(
|
||||||
|
'theme'.tr,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Theme.of(context).hintColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
items: _presentTheme
|
||||||
|
.map((SolianThemeData item) =>
|
||||||
|
DropdownMenuItem<SolianThemeData>(
|
||||||
|
value: item,
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(Icons.circle, color: item.seedColor),
|
||||||
|
const Gap(8),
|
||||||
|
Text(
|
||||||
|
item.id.tr,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
))
|
||||||
.toList(),
|
.toList(),
|
||||||
).paddingSymmetric(horizontal: 12, vertical: 8),
|
value: (_prefs?.containsKey('global_theme') ?? false)
|
||||||
|
? SolianThemeData.fromJson(
|
||||||
|
jsonDecode(_prefs!.getString('global_theme')!),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
onChanged: (SolianThemeData? value) {
|
||||||
|
context.read<ThemeSwitcher>().setThemeData(value);
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
buttonStyleData: const ButtonStyleData(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||||
|
height: 40,
|
||||||
|
width: 140,
|
||||||
|
),
|
||||||
|
menuItemStyleData: const MenuItemStyleData(
|
||||||
|
height: 40,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
CheckboxListTile(
|
||||||
|
secondary: const Icon(Icons.military_tech),
|
||||||
|
contentPadding: const EdgeInsets.symmetric(horizontal: 22),
|
||||||
|
title: Text('agedTheme'.tr),
|
||||||
|
subtitle: Text('agedThemeDesc'.tr),
|
||||||
|
value: _prefs?.getBool('aged_theme') ?? false,
|
||||||
|
onChanged: (value) {
|
||||||
|
if (value != null) {
|
||||||
|
context.read<ThemeSwitcher>().setAgedTheme(value);
|
||||||
|
}
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (!PlatformInfo.isWeb)
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Icons.wallpaper),
|
||||||
|
contentPadding: const EdgeInsets.only(left: 22, right: 31),
|
||||||
|
title: Text('appBackgroundImage'.tr),
|
||||||
|
subtitle: Text('appBackgroundImageDesc'.tr),
|
||||||
|
trailing: File('$_docBasepath/app_background_image').existsSync()
|
||||||
|
? const Icon(Icons.check_box)
|
||||||
|
: const Icon(Icons.check_box_outline_blank),
|
||||||
|
onTap: () async {
|
||||||
|
if (File('$_docBasepath/app_background_image').existsSync()) {
|
||||||
|
File('$_docBasepath/app_background_image').deleteSync();
|
||||||
|
} else {
|
||||||
|
final image = await ImagePicker().pickImage(
|
||||||
|
source: ImageSource.gallery,
|
||||||
|
);
|
||||||
|
if (image == null) return;
|
||||||
|
|
||||||
|
await File(image.path)
|
||||||
|
.copy('$_docBasepath/app_background_image');
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
),
|
),
|
||||||
_buildCaptionHeader('notification'.tr),
|
_buildCaptionHeader('notification'.tr),
|
||||||
Tooltip(
|
Tooltip(
|
||||||
@ -181,6 +270,21 @@ class _SettingScreenState extends State<SettingScreen> {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
_buildCaptionHeader('performance'.tr),
|
||||||
|
CheckboxListTile(
|
||||||
|
contentPadding: const EdgeInsets.symmetric(horizontal: 22),
|
||||||
|
secondary: const Icon(Icons.message),
|
||||||
|
title: Text('animatedMessageList'.tr),
|
||||||
|
subtitle: Text('animatedMessageListDesc'.tr),
|
||||||
|
value: _prefs?.getBool('non_animated_message_list') ?? false,
|
||||||
|
onChanged: (value) {
|
||||||
|
_prefs
|
||||||
|
?.setBool('non_animated_message_list', value ?? false)
|
||||||
|
.then((_) {
|
||||||
|
setState(() {});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
_buildCaptionHeader('more'.tr),
|
_buildCaptionHeader('more'.tr),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.delete_sweep),
|
leading: const Icon(Icons.delete_sweep),
|
||||||
|
@ -5,6 +5,7 @@ import 'package:solian/theme.dart';
|
|||||||
import 'package:solian/widgets/app_bar_title.dart';
|
import 'package:solian/widgets/app_bar_title.dart';
|
||||||
import 'package:solian/widgets/app_bar_leading.dart';
|
import 'package:solian/widgets/app_bar_leading.dart';
|
||||||
import 'package:solian/widgets/current_state_action.dart';
|
import 'package:solian/widgets/current_state_action.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
|
|
||||||
class TitleShell extends StatelessWidget {
|
class TitleShell extends StatelessWidget {
|
||||||
final bool showAppBar;
|
final bool showAppBar;
|
||||||
@ -26,7 +27,8 @@ class TitleShell extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
assert(state != null || title != null);
|
assert(state != null || title != null);
|
||||||
|
|
||||||
return Scaffold(
|
return RootContainer(
|
||||||
|
child: Scaffold(
|
||||||
appBar: showAppBar
|
appBar: showAppBar
|
||||||
? AppBar(
|
? AppBar(
|
||||||
leading: AppBarLeadingButton.adaptive(context),
|
leading: AppBarLeadingButton.adaptive(context),
|
||||||
@ -44,6 +46,7 @@ class TitleShell extends StatelessWidget {
|
|||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
body: child,
|
body: child,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:solian/models/theme.dart';
|
||||||
import 'package:solian/platform.dart';
|
import 'package:solian/platform.dart';
|
||||||
|
|
||||||
abstract class AppTheme {
|
abstract class AppTheme {
|
||||||
@ -38,6 +39,7 @@ abstract class AppTheme {
|
|||||||
brightness: brightness,
|
brightness: brightness,
|
||||||
seedColor: seedColor ?? const Color.fromRGBO(154, 98, 91, 1),
|
seedColor: seedColor ?? const Color.fromRGBO(154, 98, 91, 1),
|
||||||
),
|
),
|
||||||
|
scaffoldBackgroundColor: Colors.transparent,
|
||||||
snackBarTheme: const SnackBarThemeData(
|
snackBarTheme: const SnackBarThemeData(
|
||||||
behavior: SnackBarBehavior.floating,
|
behavior: SnackBarBehavior.floating,
|
||||||
),
|
),
|
||||||
@ -55,4 +57,36 @@ abstract class AppTheme {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ThemeData buildFromData(
|
||||||
|
Brightness brightness,
|
||||||
|
SolianThemeData data, {
|
||||||
|
bool useMaterial3 = true,
|
||||||
|
}) {
|
||||||
|
return ThemeData(
|
||||||
|
brightness: brightness,
|
||||||
|
useMaterial3: useMaterial3,
|
||||||
|
colorScheme: ColorScheme.fromSeed(
|
||||||
|
brightness: brightness,
|
||||||
|
seedColor: data.seedColor,
|
||||||
|
),
|
||||||
|
snackBarTheme: const SnackBarThemeData(
|
||||||
|
behavior: SnackBarBehavior.floating,
|
||||||
|
),
|
||||||
|
scaffoldBackgroundColor: Colors.transparent,
|
||||||
|
fontFamily: data.fontFamily ?? 'Comfortaa',
|
||||||
|
fontFamilyFallback: data.fontFamilyFallback ??
|
||||||
|
[
|
||||||
|
'NotoSansSC',
|
||||||
|
'NotoSansHK',
|
||||||
|
'NotoSansJP',
|
||||||
|
if (PlatformInfo.isWeb) 'NotoSansEmoji',
|
||||||
|
],
|
||||||
|
typography: Typography.material2021(
|
||||||
|
colorScheme: brightness == Brightness.light
|
||||||
|
? const ColorScheme.light()
|
||||||
|
: const ColorScheme.dark(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,9 +177,6 @@ class _AttachmentListState extends State<AttachmentList> {
|
|||||||
if (element == null) return const SizedBox.shrink();
|
if (element == null) return const SizedBox.shrink();
|
||||||
double ratio = element.metadata?['ratio']?.toDouble() ?? 16 / 9;
|
double ratio = element.metadata?['ratio']?.toDouble() ?? 16 / 9;
|
||||||
return Container(
|
return Container(
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
|
||||||
),
|
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxWidth: widget.columnMaxWidth,
|
maxWidth: widget.columnMaxWidth,
|
||||||
maxHeight: 640,
|
maxHeight: 640,
|
||||||
@ -247,7 +244,7 @@ class _AttachmentListState extends State<AttachmentList> {
|
|||||||
maxHeight: widget.flatMaxHeight,
|
maxHeight: widget.flatMaxHeight,
|
||||||
),
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
color: Colors.transparent,
|
||||||
border: Border.symmetric(
|
border: Border.symmetric(
|
||||||
horizontal: BorderSide(
|
horizontal: BorderSide(
|
||||||
width: 0.3,
|
width: 0.3,
|
||||||
@ -257,6 +254,7 @@ class _AttachmentListState extends State<AttachmentList> {
|
|||||||
),
|
),
|
||||||
child: CarouselSlider.builder(
|
child: CarouselSlider.builder(
|
||||||
options: CarouselOptions(
|
options: CarouselOptions(
|
||||||
|
animateToClosest: true,
|
||||||
aspectRatio: _aspectRatio,
|
aspectRatio: _aspectRatio,
|
||||||
viewportFraction:
|
viewportFraction:
|
||||||
widget.viewport ?? (widget.attachmentsId.length > 1 ? 0.95 : 1),
|
widget.viewport ?? (widget.attachmentsId.length > 1 ? 0.95 : 1),
|
||||||
@ -319,6 +317,7 @@ class AttachmentListEntry extends StatelessWidget {
|
|||||||
width: width ?? MediaQuery.of(context).size.width,
|
width: width ?? MediaQuery.of(context).size.width,
|
||||||
height: height,
|
height: height,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.transparent,
|
||||||
border: showBorder
|
border: showBorder
|
||||||
? Border.symmetric(
|
? Border.symmetric(
|
||||||
vertical: BorderSide(
|
vertical: BorderSide(
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_animate/flutter_animate.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:solian/controllers/chat_events_controller.dart';
|
import 'package:solian/controllers/chat_events_controller.dart';
|
||||||
import 'package:solian/models/channel.dart';
|
import 'package:solian/models/channel.dart';
|
||||||
@ -9,6 +10,7 @@ import 'package:solian/widgets/chat/chat_event_action.dart';
|
|||||||
import 'package:very_good_infinite_list/very_good_infinite_list.dart';
|
import 'package:very_good_infinite_list/very_good_infinite_list.dart';
|
||||||
|
|
||||||
class ChatEventList extends StatelessWidget {
|
class ChatEventList extends StatelessWidget {
|
||||||
|
final bool noAnimated;
|
||||||
final String scope;
|
final String scope;
|
||||||
final Channel channel;
|
final Channel channel;
|
||||||
final ChatEventController chatController;
|
final ChatEventController chatController;
|
||||||
@ -23,6 +25,7 @@ class ChatEventList extends StatelessWidget {
|
|||||||
required this.chatController,
|
required this.chatController,
|
||||||
required this.onEdit,
|
required this.onEdit,
|
||||||
required this.onReply,
|
required this.onReply,
|
||||||
|
this.noAnimated = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
bool _checkMessageMergeable(Event? a, Event? b) {
|
bool _checkMessageMergeable(Event? a, Event? b) {
|
||||||
@ -63,7 +66,8 @@ class ChatEventList extends StatelessWidget {
|
|||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
child: ChatEvent(
|
child: Builder(builder: (context) {
|
||||||
|
final widget = ChatEvent(
|
||||||
key: Key('m${item!.uuid}'),
|
key: Key('m${item!.uuid}'),
|
||||||
item: item,
|
item: item,
|
||||||
isMerged: isMerged,
|
isMerged: isMerged,
|
||||||
@ -71,7 +75,23 @@ class ChatEventList extends StatelessWidget {
|
|||||||
).paddingOnly(
|
).paddingOnly(
|
||||||
top: !isMerged ? 8 : 0,
|
top: !isMerged ? 8 : 0,
|
||||||
bottom: !hasMerged ? 8 : 0,
|
bottom: !hasMerged ? 8 : 0,
|
||||||
),
|
);
|
||||||
|
|
||||||
|
if (noAnimated) {
|
||||||
|
return widget;
|
||||||
|
} else {
|
||||||
|
return widget
|
||||||
|
.animate(
|
||||||
|
key: Key('animated-m${item.uuid}'),
|
||||||
|
)
|
||||||
|
.slideY(
|
||||||
|
curve: Curves.fastLinearToSlowEaseIn,
|
||||||
|
duration: 250.ms,
|
||||||
|
begin: 0.5,
|
||||||
|
end: 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}),
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
useRootNavigator: true,
|
useRootNavigator: true,
|
||||||
@ -79,7 +99,7 @@ class ChatEventList extends StatelessWidget {
|
|||||||
builder: (context) => ChatEventAction(
|
builder: (context) => ChatEventAction(
|
||||||
channel: channel,
|
channel: channel,
|
||||||
realm: channel.realm,
|
realm: channel.realm,
|
||||||
item: item,
|
item: item!,
|
||||||
onEdit: () {
|
onEdit: () {
|
||||||
onEdit(item);
|
onEdit(item);
|
||||||
},
|
},
|
||||||
|
@ -117,29 +117,15 @@ class _PostItemState extends State<PostItem> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
if (_contentHeight >= 80 && !widget.isFullContent)
|
if (_contentHeight >= 80 && !widget.isFullContent)
|
||||||
Align(
|
Opacity(
|
||||||
alignment: Alignment.bottomCenter,
|
opacity: 0.8,
|
||||||
child: IgnorePointer(
|
child: InkWell(child: Text('readMore'.tr)),
|
||||||
child: Container(
|
).paddingOnly(
|
||||||
height: 80,
|
left: 12,
|
||||||
decoration: BoxDecoration(
|
top: 4,
|
||||||
gradient: LinearGradient(
|
|
||||||
begin: Alignment.bottomCenter,
|
|
||||||
end: Alignment.topCenter,
|
|
||||||
colors: [
|
|
||||||
Theme.of(context).colorScheme.surfaceContainerLow,
|
|
||||||
Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.surface
|
|
||||||
.withOpacity(0),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
LinkExpansion(content: item.body['content']).paddingOnly(
|
LinkExpansion(content: item.body['content']).paddingOnly(
|
||||||
left: 8,
|
left: 8,
|
||||||
@ -225,33 +211,15 @@ class _PostItemState extends State<PostItem> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
if (_contentHeight >= 320 && !widget.isFullContent)
|
if (_contentHeight >= 320 && !widget.isFullContent)
|
||||||
Align(
|
Opacity(
|
||||||
alignment: Alignment.bottomCenter,
|
opacity: 0.8,
|
||||||
child: IgnorePointer(
|
child: InkWell(child: Text('readMore'.tr)),
|
||||||
child: Container(
|
).paddingOnly(
|
||||||
height: 320,
|
left: 12,
|
||||||
decoration: BoxDecoration(
|
top: 4,
|
||||||
gradient: LinearGradient(
|
|
||||||
begin: Alignment.bottomCenter,
|
|
||||||
end: Alignment.topCenter,
|
|
||||||
colors: [
|
|
||||||
(widget.backgroundColor ??
|
|
||||||
Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.surface),
|
|
||||||
(widget.backgroundColor ??
|
|
||||||
Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.surface)
|
|
||||||
.withOpacity(0),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
if (widget.item.replyTo != null && widget.isShowEmbed)
|
if (widget.item.replyTo != null && widget.isShowEmbed)
|
||||||
Container(
|
Container(
|
||||||
@ -336,8 +304,7 @@ class _PostItemState extends State<PostItem> {
|
|||||||
),
|
),
|
||||||
closedElevation: 0,
|
closedElevation: 0,
|
||||||
openElevation: 0,
|
openElevation: 0,
|
||||||
closedColor:
|
closedColor: Colors.transparent,
|
||||||
widget.backgroundColor ?? Theme.of(context).colorScheme.surface,
|
|
||||||
openColor: Theme.of(context).colorScheme.surface,
|
openColor: Theme.of(context).colorScheme.surface,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -574,7 +541,7 @@ class _PostEmbedWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
closedElevation: 0,
|
closedElevation: 0,
|
||||||
openElevation: 0,
|
openElevation: 0,
|
||||||
closedColor: Theme.of(context).colorScheme.surface,
|
closedColor: Colors.transparent,
|
||||||
openColor: Theme.of(context).colorScheme.surface,
|
openColor: Theme.of(context).colorScheme.surface,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
48
lib/widgets/root_container.dart
Normal file
48
lib/widgets/root_container.dart
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:solian/platform.dart';
|
||||||
|
|
||||||
|
class RootContainer extends StatelessWidget {
|
||||||
|
final Widget? child;
|
||||||
|
|
||||||
|
const RootContainer({super.key, this.child});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return FutureBuilder(
|
||||||
|
future: PlatformInfo.isWeb
|
||||||
|
? 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 Material(
|
||||||
|
color: Theme.of(context).colorScheme.surface,
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
backgroundBlendMode: BlendMode.darken,
|
||||||
|
color: Theme.of(context).colorScheme.surface,
|
||||||
|
image: DecorationImage(
|
||||||
|
opacity: 0.2,
|
||||||
|
image: FileImage(file),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Material(
|
||||||
|
color: Theme.of(context).colorScheme.surface,
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:solian/widgets/root_container.dart';
|
||||||
|
|
||||||
class EmptyPagePlaceholder extends StatelessWidget {
|
class EmptyPagePlaceholder extends StatelessWidget {
|
||||||
const EmptyPagePlaceholder({super.key});
|
const EmptyPagePlaceholder({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Material(
|
return RootContainer(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: Center(
|
child: Center(
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||||
|
@ -2,7 +2,7 @@ name: solian
|
|||||||
description: "The Solar Network App"
|
description: "The Solar Network App"
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
|
|
||||||
version: 1.3.6+2
|
version: 1.3.6+3
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.3.4 <4.0.0"
|
sdk: ">=3.3.4 <4.0.0"
|
||||||
|
Reference in New Issue
Block a user