Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
107379d9fe | |||
0d807b8708 | |||
ac1b3fe15c | |||
5853de32a2 | |||
eac1be365e |
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"annvisery"
|
||||||
|
]
|
||||||
|
}
|
@ -54,6 +54,7 @@
|
|||||||
"about": "About",
|
"about": "About",
|
||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
|
"insert": "Insert",
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
"settingsNotificationBgService": "Background notification service",
|
"settingsNotificationBgService": "Background notification service",
|
||||||
"settingsNotificationBgServiceDesc": "A notification service is always installed on the device, so that some devices that do not support push notifications can receive notifications in the background. When this feature is enabled, push notifications will not be registered with the server, and you will always appear to be online in the eyes of others (except for invisible). You may need to turn off power and traffic optimization in the settings.",
|
"settingsNotificationBgServiceDesc": "A notification service is always installed on the device, so that some devices that do not support push notifications can receive notifications in the background. When this feature is enabled, push notifications will not be registered with the server, and you will always appear to be online in the eyes of others (except for invisible). You may need to turn off power and traffic optimization in the settings.",
|
||||||
@ -366,6 +367,7 @@
|
|||||||
"bsPreparingData": "Preparing User Data",
|
"bsPreparingData": "Preparing User Data",
|
||||||
"bsRegisteringPushNotify": "Enabling Push Notifications",
|
"bsRegisteringPushNotify": "Enabling Push Notifications",
|
||||||
"bsDismissibleErrorHint": "Click anywhere to ignore this error",
|
"bsDismissibleErrorHint": "Click anywhere to ignore this error",
|
||||||
|
"bsContinuable": "Click anywhere to continue",
|
||||||
"postShareContent": "@content\n\n@username on the Solar Network\nCheck it out: @link",
|
"postShareContent": "@content\n\n@username on the Solar Network\nCheck it out: @link",
|
||||||
"postShareSubject": "@title by @username on Solar Network",
|
"postShareSubject": "@title by @username on Solar Network",
|
||||||
"themeColor": "Global Theme Color",
|
"themeColor": "Global Theme Color",
|
||||||
@ -490,5 +492,7 @@
|
|||||||
"shotOn": "Shot on @device",
|
"shotOn": "Shot on @device",
|
||||||
"unread": "Unread",
|
"unread": "Unread",
|
||||||
"searchTook": "Took @time",
|
"searchTook": "Took @time",
|
||||||
"searchResult": "@count Matches"
|
"searchResult": "@count Matches",
|
||||||
|
"happyBirthday": "Happy birthday @name!",
|
||||||
|
"happyBirthdayDesc": "Today is your @count birthday"
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
"about": "关于",
|
"about": "关于",
|
||||||
"edit": "编辑",
|
"edit": "编辑",
|
||||||
"delete": "删除",
|
"delete": "删除",
|
||||||
|
"insert": "插入",
|
||||||
"settings": "设置",
|
"settings": "设置",
|
||||||
"settingsNotificationBgService": "常驻通知服务",
|
"settingsNotificationBgService": "常驻通知服务",
|
||||||
"settingsNotificationBgServiceDesc": "在设备常驻一个通知服务,使得部分不支持推送通知的设备可以在后台收到通知;启用该功能的情况下不会向服务器注册推送通知,并且你会始终在他人眼中成为在线(隐身除外);可能需要在设置中关闭电量与流量优化。",
|
"settingsNotificationBgServiceDesc": "在设备常驻一个通知服务,使得部分不支持推送通知的设备可以在后台收到通知;启用该功能的情况下不会向服务器注册推送通知,并且你会始终在他人眼中成为在线(隐身除外);可能需要在设置中关闭电量与流量优化。",
|
||||||
@ -362,6 +363,7 @@
|
|||||||
"bsPreparingData": "正在准备用户资料",
|
"bsPreparingData": "正在准备用户资料",
|
||||||
"bsRegisteringPushNotify": "正在启用推送通知",
|
"bsRegisteringPushNotify": "正在启用推送通知",
|
||||||
"bsDismissibleErrorHint": "点击任意地方忽略此错误",
|
"bsDismissibleErrorHint": "点击任意地方忽略此错误",
|
||||||
|
"bsContinuable": "点击任意处继续",
|
||||||
"postShareContent": "@content\n\n@username 在 Solar Network\n原帖地址:@link",
|
"postShareContent": "@content\n\n@username 在 Solar Network\n原帖地址:@link",
|
||||||
"postShareSubject": "@username 在 Solar Network 发表的 @title",
|
"postShareSubject": "@username 在 Solar Network 发表的 @title",
|
||||||
"themeColor": "全局主题色",
|
"themeColor": "全局主题色",
|
||||||
@ -486,5 +488,7 @@
|
|||||||
"shotOn": "由 @device 拍摄",
|
"shotOn": "由 @device 拍摄",
|
||||||
"unread": "未读",
|
"unread": "未读",
|
||||||
"searchTook": "耗时 @time",
|
"searchTook": "耗时 @time",
|
||||||
"searchResult": "匹配到 @count 条结果"
|
"searchResult": "匹配到 @count 条结果",
|
||||||
|
"happyBirthday": "生日快乐,@name!",
|
||||||
|
"happyBirthdayDesc": "今天是你的第 @count 个生日"
|
||||||
}
|
}
|
||||||
|
@ -462,8 +462,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/wakelock_plus/ios"
|
:path: ".symlinks/plugins/wakelock_plus/ios"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db
|
connectivity_plus: 4c41c08fc6d7c91f63bc7aec70ffe3730b04f563
|
||||||
device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d
|
device_info_plus: bf2e3232933866d73fe290f2942f2156cdd10342
|
||||||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||||
file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655
|
file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655
|
||||||
@ -508,7 +508,7 @@ SPEC CHECKSUMS:
|
|||||||
media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a
|
media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a
|
||||||
media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e
|
media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e
|
||||||
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
||||||
package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c
|
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
|
||||||
pasteboard: 982969ebaa7c78af3e6cc7761e8f5e77565d9ce0
|
pasteboard: 982969ebaa7c78af3e6cc7761e8f5e77565d9ce0
|
||||||
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
|
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
|
||||||
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
|
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
|
||||||
@ -519,7 +519,7 @@ SPEC CHECKSUMS:
|
|||||||
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
||||||
screen_brightness_ios: 715ca807df953bf676d339f11464e438143ee625
|
screen_brightness_ios: 715ca807df953bf676d339f11464e438143ee625
|
||||||
SDWebImage: 8a6b7b160b4d710e2a22b6900e25301075c34cb3
|
SDWebImage: 8a6b7b160b4d710e2a22b6900e25301075c34cb3
|
||||||
share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad
|
share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
|
||||||
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
|
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
|
||||||
sqflite_darwin: a553b1fd6fe66f53bbb0fe5b4f5bab93f08d7a13
|
sqflite_darwin: a553b1fd6fe66f53bbb0fe5b4f5bab93f08d7a13
|
||||||
sqlite3: 0bb0e6389d824e40296f531b858a2a0b71c0d2fb
|
sqlite3: 0bb0e6389d824e40296f531b858a2a0b71c0d2fb
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:confetti/confetti.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@ -10,6 +11,7 @@ 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/account.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/content/realm.dart';
|
import 'package:solian/providers/content/realm.dart';
|
||||||
@ -23,6 +25,11 @@ 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';
|
||||||
|
|
||||||
|
enum BootstrapperSpecialState {
|
||||||
|
userBirthday,
|
||||||
|
appAnniversary,
|
||||||
|
}
|
||||||
|
|
||||||
class BootstrapperShell extends StatefulWidget {
|
class BootstrapperShell extends StatefulWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
@ -43,6 +50,9 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
|
|||||||
|
|
||||||
int _periodCursor = 0;
|
int _periodCursor = 0;
|
||||||
|
|
||||||
|
// Special state is some special event triggered after bootstrapping
|
||||||
|
BootstrapperSpecialState? _specialState;
|
||||||
|
|
||||||
final Completer _bootCompleter = Completer();
|
final Completer _bootCompleter = Completer();
|
||||||
|
|
||||||
void _requestRating() async {
|
void _requestRating() async {
|
||||||
@ -206,6 +216,19 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
|
|||||||
if (auth.isAuthorized.isTrue)
|
if (auth.isAuthorized.isTrue)
|
||||||
Get.find<RealmProvider>().refreshAvailableRealms(),
|
Get.find<RealmProvider>().refreshAvailableRealms(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (auth.isAuthorized.isTrue && auth.userProfile.value != null) {
|
||||||
|
final account = Account.fromJson(auth.userProfile.value!);
|
||||||
|
if (account.profile?.birthday != null) {
|
||||||
|
final birthDate = account.profile!.birthday!.toLocal();
|
||||||
|
final isBirthday = birthDate.day == DateTime.now().day;
|
||||||
|
if (isBirthday) {
|
||||||
|
setState(
|
||||||
|
() => _specialState = BootstrapperSpecialState.userBirthday,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
context.showErrorDialog(e);
|
context.showErrorDialog(e);
|
||||||
}
|
}
|
||||||
@ -355,8 +378,142 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
} else if (_specialState != null) {
|
||||||
|
return GestureDetector(
|
||||||
|
child: RootContainer(
|
||||||
|
child: switch (_specialState) {
|
||||||
|
BootstrapperSpecialState.appAnniversary => const Placeholder(),
|
||||||
|
_ => _BirthdaySpecialScreen(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
setState(() => _specialState = null);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return widget.child;
|
return widget.child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _BirthdaySpecialScreen extends StatefulWidget {
|
||||||
|
const _BirthdaySpecialScreen();
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_BirthdaySpecialScreen> createState() => _BirthdaySpecialScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _BirthdaySpecialScreenState extends State<_BirthdaySpecialScreen> {
|
||||||
|
late final ConfettiController _confettiController =
|
||||||
|
ConfettiController(duration: const Duration(seconds: 10));
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_confettiController.play();
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_confettiController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
Color get _unFocusColor =>
|
||||||
|
Theme.of(context).colorScheme.onSurface.withOpacity(0.75);
|
||||||
|
|
||||||
|
String _toOrdinal(int num) {
|
||||||
|
if (num >= 11 && num <= 13) {
|
||||||
|
return '${num}th';
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (num % 10) {
|
||||||
|
case 1:
|
||||||
|
return '${num}st';
|
||||||
|
case 2:
|
||||||
|
return '${num}nd';
|
||||||
|
case 3:
|
||||||
|
return '${num}rd';
|
||||||
|
default:
|
||||||
|
return '${num}th';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final AuthProvider auth = Get.find();
|
||||||
|
final account = Account.fromJson(auth.userProfile.value!);
|
||||||
|
|
||||||
|
final birthDate = account.profile!.birthday!.toLocal();
|
||||||
|
final birthdayCount = DateTime.now().difference(birthDate).inDays ~/ 365;
|
||||||
|
|
||||||
|
return Stack(
|
||||||
|
children: <Widget>[
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: ConfettiWidget(
|
||||||
|
confettiController: _confettiController,
|
||||||
|
blastDirectionality: BlastDirectionality.explosive,
|
||||||
|
shouldLoop: true,
|
||||||
|
colors: const [
|
||||||
|
Colors.green,
|
||||||
|
Colors.blue,
|
||||||
|
Colors.pink,
|
||||||
|
Colors.orange,
|
||||||
|
Colors.purple
|
||||||
|
],
|
||||||
|
maxBlastForce: 30,
|
||||||
|
minBlastForce: 15,
|
||||||
|
emissionFrequency: 0.05,
|
||||||
|
numberOfParticles: 20,
|
||||||
|
gravity: 0.2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Align(
|
||||||
|
child: CenteredContainer(
|
||||||
|
maxWidth: 320,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'🎂',
|
||||||
|
style: TextStyle(fontSize: 60),
|
||||||
|
),
|
||||||
|
const Gap(8),
|
||||||
|
Text(
|
||||||
|
'happyBirthday'.trParams({
|
||||||
|
'name': account.profile?.firstName != null
|
||||||
|
? [
|
||||||
|
account.profile?.firstName,
|
||||||
|
account.profile?.lastName
|
||||||
|
].join(' ')
|
||||||
|
: '@${account.name}',
|
||||||
|
}),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'happyBirthdayDesc'.trParams({
|
||||||
|
'count': _toOrdinal(birthdayCount),
|
||||||
|
}),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
|
),
|
||||||
|
const Gap(8),
|
||||||
|
Text(
|
||||||
|
'bsContinuable'.tr,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 13,
|
||||||
|
color: _unFocusColor,
|
||||||
|
),
|
||||||
|
).paddingOnly(bottom: 5),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -125,6 +125,21 @@ class PostEditorController extends GetxController {
|
|||||||
onRemove: (String value) {
|
onRemove: (String value) {
|
||||||
attachments.remove(value);
|
attachments.remove(value);
|
||||||
},
|
},
|
||||||
|
onInsert: (String str) {
|
||||||
|
final text = contentController.text;
|
||||||
|
final selection = contentController.selection;
|
||||||
|
final newText = text.replaceRange(
|
||||||
|
selection.start,
|
||||||
|
selection.end,
|
||||||
|
str,
|
||||||
|
);
|
||||||
|
contentController.value = TextEditingValue(
|
||||||
|
text: newText,
|
||||||
|
selection: TextSelection.collapsed(
|
||||||
|
offset: selection.baseOffset + str.length,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -299,53 +299,71 @@ typedef $$LocalMessageEventTableTableUpdateCompanionBuilder
|
|||||||
});
|
});
|
||||||
|
|
||||||
class $$LocalMessageEventTableTableFilterComposer
|
class $$LocalMessageEventTableTableFilterComposer
|
||||||
extends FilterComposer<_$AppDatabase, $LocalMessageEventTableTable> {
|
extends Composer<_$AppDatabase, $LocalMessageEventTableTable> {
|
||||||
$$LocalMessageEventTableTableFilterComposer(super.$state);
|
$$LocalMessageEventTableTableFilterComposer({
|
||||||
ColumnFilters<int> get id => $state.composableBuilder(
|
required super.$db,
|
||||||
column: $state.table.id,
|
required super.$table,
|
||||||
builder: (column, joinBuilders) =>
|
super.joinBuilder,
|
||||||
ColumnFilters(column, joinBuilders: joinBuilders));
|
super.$addJoinBuilderToRootComposer,
|
||||||
|
super.$removeJoinBuilderFromRootComposer,
|
||||||
|
});
|
||||||
|
ColumnFilters<int> get id => $composableBuilder(
|
||||||
|
column: $table.id, builder: (column) => ColumnFilters(column));
|
||||||
|
|
||||||
ColumnFilters<int> get channelId => $state.composableBuilder(
|
ColumnFilters<int> get channelId => $composableBuilder(
|
||||||
column: $state.table.channelId,
|
column: $table.channelId, builder: (column) => ColumnFilters(column));
|
||||||
builder: (column, joinBuilders) =>
|
|
||||||
ColumnFilters(column, joinBuilders: joinBuilders));
|
|
||||||
|
|
||||||
ColumnWithTypeConverterFilters<Event?, Event, String> get data =>
|
ColumnWithTypeConverterFilters<Event?, Event, String> get data =>
|
||||||
$state.composableBuilder(
|
$composableBuilder(
|
||||||
column: $state.table.data,
|
column: $table.data,
|
||||||
builder: (column, joinBuilders) => ColumnWithTypeConverterFilters(
|
builder: (column) => ColumnWithTypeConverterFilters(column));
|
||||||
column,
|
|
||||||
joinBuilders: joinBuilders));
|
|
||||||
|
|
||||||
ColumnFilters<DateTime> get createdAt => $state.composableBuilder(
|
ColumnFilters<DateTime> get createdAt => $composableBuilder(
|
||||||
column: $state.table.createdAt,
|
column: $table.createdAt, builder: (column) => ColumnFilters(column));
|
||||||
builder: (column, joinBuilders) =>
|
|
||||||
ColumnFilters(column, joinBuilders: joinBuilders));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$LocalMessageEventTableTableOrderingComposer
|
class $$LocalMessageEventTableTableOrderingComposer
|
||||||
extends OrderingComposer<_$AppDatabase, $LocalMessageEventTableTable> {
|
extends Composer<_$AppDatabase, $LocalMessageEventTableTable> {
|
||||||
$$LocalMessageEventTableTableOrderingComposer(super.$state);
|
$$LocalMessageEventTableTableOrderingComposer({
|
||||||
ColumnOrderings<int> get id => $state.composableBuilder(
|
required super.$db,
|
||||||
column: $state.table.id,
|
required super.$table,
|
||||||
builder: (column, joinBuilders) =>
|
super.joinBuilder,
|
||||||
ColumnOrderings(column, joinBuilders: joinBuilders));
|
super.$addJoinBuilderToRootComposer,
|
||||||
|
super.$removeJoinBuilderFromRootComposer,
|
||||||
|
});
|
||||||
|
ColumnOrderings<int> get id => $composableBuilder(
|
||||||
|
column: $table.id, builder: (column) => ColumnOrderings(column));
|
||||||
|
|
||||||
ColumnOrderings<int> get channelId => $state.composableBuilder(
|
ColumnOrderings<int> get channelId => $composableBuilder(
|
||||||
column: $state.table.channelId,
|
column: $table.channelId, builder: (column) => ColumnOrderings(column));
|
||||||
builder: (column, joinBuilders) =>
|
|
||||||
ColumnOrderings(column, joinBuilders: joinBuilders));
|
|
||||||
|
|
||||||
ColumnOrderings<String> get data => $state.composableBuilder(
|
ColumnOrderings<String> get data => $composableBuilder(
|
||||||
column: $state.table.data,
|
column: $table.data, builder: (column) => ColumnOrderings(column));
|
||||||
builder: (column, joinBuilders) =>
|
|
||||||
ColumnOrderings(column, joinBuilders: joinBuilders));
|
|
||||||
|
|
||||||
ColumnOrderings<DateTime> get createdAt => $state.composableBuilder(
|
ColumnOrderings<DateTime> get createdAt => $composableBuilder(
|
||||||
column: $state.table.createdAt,
|
column: $table.createdAt, builder: (column) => ColumnOrderings(column));
|
||||||
builder: (column, joinBuilders) =>
|
}
|
||||||
ColumnOrderings(column, joinBuilders: joinBuilders));
|
|
||||||
|
class $$LocalMessageEventTableTableAnnotationComposer
|
||||||
|
extends Composer<_$AppDatabase, $LocalMessageEventTableTable> {
|
||||||
|
$$LocalMessageEventTableTableAnnotationComposer({
|
||||||
|
required super.$db,
|
||||||
|
required super.$table,
|
||||||
|
super.joinBuilder,
|
||||||
|
super.$addJoinBuilderToRootComposer,
|
||||||
|
super.$removeJoinBuilderFromRootComposer,
|
||||||
|
});
|
||||||
|
GeneratedColumn<int> get id =>
|
||||||
|
$composableBuilder(column: $table.id, builder: (column) => column);
|
||||||
|
|
||||||
|
GeneratedColumn<int> get channelId =>
|
||||||
|
$composableBuilder(column: $table.channelId, builder: (column) => column);
|
||||||
|
|
||||||
|
GeneratedColumnWithTypeConverter<Event?, String> get data =>
|
||||||
|
$composableBuilder(column: $table.data, builder: (column) => column);
|
||||||
|
|
||||||
|
GeneratedColumn<DateTime> get createdAt =>
|
||||||
|
$composableBuilder(column: $table.createdAt, builder: (column) => column);
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$LocalMessageEventTableTableTableManager extends RootTableManager<
|
class $$LocalMessageEventTableTableTableManager extends RootTableManager<
|
||||||
@ -354,6 +372,7 @@ class $$LocalMessageEventTableTableTableManager extends RootTableManager<
|
|||||||
LocalMessageEventTableData,
|
LocalMessageEventTableData,
|
||||||
$$LocalMessageEventTableTableFilterComposer,
|
$$LocalMessageEventTableTableFilterComposer,
|
||||||
$$LocalMessageEventTableTableOrderingComposer,
|
$$LocalMessageEventTableTableOrderingComposer,
|
||||||
|
$$LocalMessageEventTableTableAnnotationComposer,
|
||||||
$$LocalMessageEventTableTableCreateCompanionBuilder,
|
$$LocalMessageEventTableTableCreateCompanionBuilder,
|
||||||
$$LocalMessageEventTableTableUpdateCompanionBuilder,
|
$$LocalMessageEventTableTableUpdateCompanionBuilder,
|
||||||
(
|
(
|
||||||
@ -368,10 +387,15 @@ class $$LocalMessageEventTableTableTableManager extends RootTableManager<
|
|||||||
: super(TableManagerState(
|
: super(TableManagerState(
|
||||||
db: db,
|
db: db,
|
||||||
table: table,
|
table: table,
|
||||||
filteringComposer: $$LocalMessageEventTableTableFilterComposer(
|
createFilteringComposer: () =>
|
||||||
ComposerState(db, table)),
|
$$LocalMessageEventTableTableFilterComposer(
|
||||||
orderingComposer: $$LocalMessageEventTableTableOrderingComposer(
|
$db: db, $table: table),
|
||||||
ComposerState(db, table)),
|
createOrderingComposer: () =>
|
||||||
|
$$LocalMessageEventTableTableOrderingComposer(
|
||||||
|
$db: db, $table: table),
|
||||||
|
createComputedFieldComposer: () =>
|
||||||
|
$$LocalMessageEventTableTableAnnotationComposer(
|
||||||
|
$db: db, $table: table),
|
||||||
updateCompanionCallback: ({
|
updateCompanionCallback: ({
|
||||||
Value<int> id = const Value.absent(),
|
Value<int> id = const Value.absent(),
|
||||||
Value<int> channelId = const Value.absent(),
|
Value<int> channelId = const Value.absent(),
|
||||||
@ -410,6 +434,7 @@ typedef $$LocalMessageEventTableTableProcessedTableManager
|
|||||||
LocalMessageEventTableData,
|
LocalMessageEventTableData,
|
||||||
$$LocalMessageEventTableTableFilterComposer,
|
$$LocalMessageEventTableTableFilterComposer,
|
||||||
$$LocalMessageEventTableTableOrderingComposer,
|
$$LocalMessageEventTableTableOrderingComposer,
|
||||||
|
$$LocalMessageEventTableTableAnnotationComposer,
|
||||||
$$LocalMessageEventTableTableCreateCompanionBuilder,
|
$$LocalMessageEventTableTableCreateCompanionBuilder,
|
||||||
$$LocalMessageEventTableTableUpdateCompanionBuilder,
|
$$LocalMessageEventTableTableUpdateCompanionBuilder,
|
||||||
(
|
(
|
||||||
|
@ -121,9 +121,11 @@ class _NotificationScreenState extends State<NotificationScreen> {
|
|||||||
Badge(
|
Badge(
|
||||||
label: Row(
|
label: Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(
|
Icon(
|
||||||
Icons.new_releases_outlined,
|
Icons.new_releases_outlined,
|
||||||
color: Colors.white,
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.onSurface,
|
||||||
size: 12,
|
size: 12,
|
||||||
),
|
),
|
||||||
const Gap(4),
|
const Gap(4),
|
||||||
|
@ -348,7 +348,7 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
|
|||||||
detail: _userinfo,
|
detail: _userinfo,
|
||||||
profile: _userinfo!.profile,
|
profile: _userinfo!.profile,
|
||||||
extraWidgets: [
|
extraWidgets: [
|
||||||
if (_dailySignRecords.isNotEmpty)
|
if (_dailySignRecords.length > 1)
|
||||||
Card(
|
Card(
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 180,
|
height: 180,
|
||||||
|
@ -198,7 +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 RootContainer(
|
return ResponsiveRootContainer(
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: widget.hideAppBar
|
appBar: widget.hideAppBar
|
||||||
? null
|
? null
|
||||||
|
@ -33,12 +33,14 @@ class AttachmentEditorPopup extends StatefulWidget {
|
|||||||
final List<String>? initialAttachments;
|
final List<String>? initialAttachments;
|
||||||
final void Function(String) onAdd;
|
final void Function(String) onAdd;
|
||||||
final void Function(String) onRemove;
|
final void Function(String) onRemove;
|
||||||
|
final void Function(String)? onInsert;
|
||||||
|
|
||||||
const AttachmentEditorPopup({
|
const AttachmentEditorPopup({
|
||||||
super.key,
|
super.key,
|
||||||
required this.pool,
|
required this.pool,
|
||||||
required this.onAdd,
|
required this.onAdd,
|
||||||
required this.onRemove,
|
required this.onRemove,
|
||||||
|
this.onInsert,
|
||||||
this.singleMode = false,
|
this.singleMode = false,
|
||||||
this.imageOnly = false,
|
this.imageOnly = false,
|
||||||
this.autoUpload = false,
|
this.autoUpload = false,
|
||||||
@ -229,7 +231,10 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
|
|||||||
.listMetadata(widget.initialAttachments ?? List.empty())
|
.listMetadata(widget.initialAttachments ?? List.empty())
|
||||||
.then((result) {
|
.then((result) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_attachments = List.from(result, growable: true);
|
_attachments = List.from(
|
||||||
|
result.where((x) => x != null),
|
||||||
|
growable: true,
|
||||||
|
);
|
||||||
_isBusy = false;
|
_isBusy = false;
|
||||||
_isFirstTimeBusy = false;
|
_isFirstTimeBusy = false;
|
||||||
});
|
});
|
||||||
@ -554,6 +559,22 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
|
|||||||
setState(() => _attachments.removeAt(idx));
|
setState(() => _attachments.removeAt(idx));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
if (widget.onInsert != null)
|
||||||
|
PopupMenuItem(
|
||||||
|
child: ListTile(
|
||||||
|
title: Text('insert'.tr),
|
||||||
|
leading: const Icon(Icons.insert_link),
|
||||||
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
widget.onInsert!(
|
||||||
|
'',
|
||||||
|
);
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -265,8 +265,15 @@ class _AttachmentFullScreenState extends State<AttachmentFullScreen> {
|
|||||||
'ISO${widget.item.metadata?['exif']?['ISO']}',
|
'ISO${widget.item.metadata?['exif']?['ISO']}',
|
||||||
style: metaTextStyle,
|
style: metaTextStyle,
|
||||||
).paddingOnly(right: 2),
|
).paddingOnly(right: 2),
|
||||||
if (widget.item.metadata?['exif']?['Megapixels'] !=
|
if (widget.item.metadata?['exif']?['Aperture'] !=
|
||||||
null)
|
null)
|
||||||
|
Text(
|
||||||
|
'f/${widget.item.metadata?['exif']?['Aperture']}',
|
||||||
|
style: metaTextStyle,
|
||||||
|
).paddingOnly(right: 2),
|
||||||
|
if (widget.item.metadata?['exif']?['Megapixels'] !=
|
||||||
|
null &&
|
||||||
|
widget.item.metadata?['exif']?['Model'] != null)
|
||||||
Text(
|
Text(
|
||||||
'${widget.item.metadata?['exif']?['Megapixels']}MP',
|
'${widget.item.metadata?['exif']?['Megapixels']}MP',
|
||||||
style: metaTextStyle,
|
style: metaTextStyle,
|
||||||
@ -280,6 +287,16 @@ class _AttachmentFullScreenState extends State<AttachmentFullScreen> {
|
|||||||
'${widget.item.metadata?['width']}x${widget.item.metadata?['height']}',
|
'${widget.item.metadata?['width']}x${widget.item.metadata?['height']}',
|
||||||
style: metaTextStyle,
|
style: metaTextStyle,
|
||||||
),
|
),
|
||||||
|
if (widget.item.metadata?['ratio'] != null)
|
||||||
|
Text(
|
||||||
|
(widget.item.metadata?['ratio'] as num)
|
||||||
|
.toStringAsFixed(2),
|
||||||
|
style: metaTextStyle,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
widget.item.mimetype,
|
||||||
|
style: metaTextStyle,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -420,11 +420,13 @@ class AttachmentListEntry extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
if (item!.isMature && !showMature)
|
if (item!.isMature && !showMature)
|
||||||
BackdropFilter(
|
ClipRect(
|
||||||
filter: ImageFilter.blur(sigmaX: 100, sigmaY: 100),
|
child: BackdropFilter(
|
||||||
child: Container(
|
filter: ImageFilter.blur(sigmaX: 100, sigmaY: 100),
|
||||||
decoration: BoxDecoration(
|
child: Container(
|
||||||
color: Colors.black.withOpacity(0.5),
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.black.withOpacity(0.5),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -2,12 +2,13 @@ import 'dart:ui';
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||||
import 'package:gap/gap.dart';
|
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:markdown/markdown.dart' as markdown;
|
import 'package:markdown/markdown.dart' as markdown;
|
||||||
import 'package:path/path.dart';
|
import 'package:path/path.dart';
|
||||||
|
import 'package:solian/models/attachment.dart';
|
||||||
import 'package:solian/providers/stickers.dart';
|
import 'package:solian/providers/stickers.dart';
|
||||||
|
import 'package:solian/widgets/attachments/attachment_item.dart';
|
||||||
import 'package:solian/widgets/attachments/attachment_list.dart';
|
import 'package:solian/widgets/attachments/attachment_list.dart';
|
||||||
import 'package:solian/widgets/auto_cache_image.dart';
|
import 'package:solian/widgets/auto_cache_image.dart';
|
||||||
import 'package:syntax_highlight/syntax_highlight.dart';
|
import 'package:syntax_highlight/syntax_highlight.dart';
|
||||||
@ -15,9 +16,10 @@ import 'package:url_launcher/url_launcher_string.dart';
|
|||||||
|
|
||||||
import 'account/account_profile_popup.dart';
|
import 'account/account_profile_popup.dart';
|
||||||
|
|
||||||
class MarkdownTextContent extends StatelessWidget {
|
class MarkdownTextContent extends StatefulWidget {
|
||||||
final String content;
|
final String content;
|
||||||
final String parentId;
|
final String parentId;
|
||||||
|
final List<Attachment>? attachments;
|
||||||
final bool isSelectable;
|
final bool isSelectable;
|
||||||
final bool isLargeText;
|
final bool isLargeText;
|
||||||
final bool isAutoWarp;
|
final bool isAutoWarp;
|
||||||
@ -26,195 +28,221 @@ class MarkdownTextContent extends StatelessWidget {
|
|||||||
super.key,
|
super.key,
|
||||||
required this.content,
|
required this.content,
|
||||||
required this.parentId,
|
required this.parentId,
|
||||||
|
this.attachments,
|
||||||
this.isSelectable = false,
|
this.isSelectable = false,
|
||||||
this.isLargeText = false,
|
this.isLargeText = false,
|
||||||
this.isAutoWarp = false,
|
this.isAutoWarp = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
Widget _buildContent(BuildContext context) {
|
@override
|
||||||
|
State<MarkdownTextContent> createState() => _MarkdownTextContentState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MarkdownTextContentState extends State<MarkdownTextContent> {
|
||||||
|
final List<int> _stickerSizes = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
initState() {
|
||||||
|
super.initState();
|
||||||
final stickerRegex = RegExp(r':([-\w]+):');
|
final stickerRegex = RegExp(r':([-\w]+):');
|
||||||
|
|
||||||
// Split the content into paragraphs
|
// Split the content into paragraphs
|
||||||
final paragraphs = content.split(RegExp(r'\n\s*\n'));
|
final paragraphs = widget.content.split(RegExp(r'\n\s*\n'));
|
||||||
|
|
||||||
// Iterate over each paragraph to process stickers individually
|
// Iterate over each paragraph to process stickers individually
|
||||||
List<Widget> contentWidgets = [];
|
|
||||||
for (var idx = 0; idx < paragraphs.length; idx++) {
|
for (var idx = 0; idx < paragraphs.length; idx++) {
|
||||||
// Getting paragraph
|
// Getting paragraph
|
||||||
var paragraph = paragraphs[idx];
|
var paragraph = paragraphs[idx];
|
||||||
|
|
||||||
// Matching stickers
|
// Matching stickers
|
||||||
final stickerMatch = stickerRegex.allMatches(paragraph);
|
final stickerMatch = stickerRegex.allMatches(paragraph);
|
||||||
final isOnlySticker =
|
if (stickerMatch.length > 3) {
|
||||||
paragraph.replaceAll(stickerRegex, '').trim().isEmpty;
|
_stickerSizes.addAll(List.filled(stickerMatch.length, 16));
|
||||||
|
} else if (stickerMatch.length > 1) {
|
||||||
contentWidgets.add(
|
_stickerSizes.addAll(List.filled(stickerMatch.length, 32));
|
||||||
Markdown(
|
} else {
|
||||||
shrinkWrap: true,
|
_stickerSizes.addAll(List.filled(stickerMatch.length, 128));
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
|
||||||
data: paragraph,
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
styleSheet: MarkdownStyleSheet.fromTheme(
|
|
||||||
Theme.of(context),
|
|
||||||
).copyWith(
|
|
||||||
textScaler: TextScaler.linear(isLargeText ? 1.1 : 1),
|
|
||||||
blockquote: TextStyle(
|
|
||||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
|
||||||
),
|
|
||||||
blockquoteDecoration: BoxDecoration(
|
|
||||||
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
|
||||||
),
|
|
||||||
horizontalRuleDecoration: BoxDecoration(
|
|
||||||
border: Border(
|
|
||||||
top: BorderSide(
|
|
||||||
width: 1.0,
|
|
||||||
color: Theme.of(context).dividerColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
codeblockDecoration: BoxDecoration(
|
|
||||||
border: Border.all(
|
|
||||||
color: Theme.of(context).dividerColor,
|
|
||||||
width: 0.3,
|
|
||||||
),
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
|
||||||
color: Theme.of(context).colorScheme.surface.withOpacity(0.5),
|
|
||||||
)),
|
|
||||||
builders: {
|
|
||||||
'code': _MarkdownTextCodeElement(),
|
|
||||||
},
|
|
||||||
softLineBreak: true,
|
|
||||||
extensionSet: markdown.ExtensionSet(
|
|
||||||
<markdown.BlockSyntax>[
|
|
||||||
markdown.CodeBlockSyntax(),
|
|
||||||
...markdown.ExtensionSet.commonMark.blockSyntaxes,
|
|
||||||
...markdown.ExtensionSet.gitHubFlavored.blockSyntaxes,
|
|
||||||
],
|
|
||||||
<markdown.InlineSyntax>[
|
|
||||||
if (isAutoWarp) markdown.LineBreakSyntax(),
|
|
||||||
_UserNameCardInlineSyntax(),
|
|
||||||
_CustomEmoteInlineSyntax(),
|
|
||||||
markdown.AutolinkSyntax(),
|
|
||||||
markdown.AutolinkExtensionSyntax(),
|
|
||||||
markdown.CodeSyntax(),
|
|
||||||
...markdown.ExtensionSet.commonMark.inlineSyntaxes,
|
|
||||||
...markdown.ExtensionSet.gitHubFlavored.inlineSyntaxes
|
|
||||||
],
|
|
||||||
),
|
|
||||||
onTapLink: (text, href, title) async {
|
|
||||||
if (href == null) return;
|
|
||||||
if (href.startsWith('solink://')) {
|
|
||||||
final segments = href.replaceFirst('solink://', '').split('/');
|
|
||||||
switch (segments[0]) {
|
|
||||||
case 'users':
|
|
||||||
showModalBottomSheet(
|
|
||||||
useRootNavigator: true,
|
|
||||||
isScrollControlled: true,
|
|
||||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
|
||||||
context: context,
|
|
||||||
builder: (context) => AccountProfilePopup(
|
|
||||||
name: segments[1],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await launchUrlString(
|
|
||||||
href,
|
|
||||||
mode: LaunchMode.externalApplication,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
imageBuilder: (uri, title, alt) {
|
|
||||||
var url = uri.toString();
|
|
||||||
double? width, height;
|
|
||||||
BoxFit? fit;
|
|
||||||
if (url.startsWith('solink://')) {
|
|
||||||
final segments = url.replaceFirst('solink://', '').split('/');
|
|
||||||
switch (segments[0]) {
|
|
||||||
case 'stickers':
|
|
||||||
double radius = 8;
|
|
||||||
final StickerProvider sticker = Get.find();
|
|
||||||
|
|
||||||
// Adjust sticker size based on the sticker count in this paragraph
|
|
||||||
if (stickerMatch.length <= 1 && isOnlySticker) {
|
|
||||||
width = 128;
|
|
||||||
height = 128;
|
|
||||||
} else if (stickerMatch.length <= 3 && isOnlySticker) {
|
|
||||||
width = 32;
|
|
||||||
height = 32;
|
|
||||||
} else {
|
|
||||||
radius = 4;
|
|
||||||
width = 16;
|
|
||||||
height = 16;
|
|
||||||
}
|
|
||||||
fit = BoxFit.contain;
|
|
||||||
return ClipRRect(
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(radius)),
|
|
||||||
child: Container(
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
|
||||||
child: FutureBuilder(
|
|
||||||
future: sticker.getStickerByAlias(segments[1]),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (!snapshot.hasData) {
|
|
||||||
return const Center(
|
|
||||||
child: CircularProgressIndicator());
|
|
||||||
}
|
|
||||||
return AutoCacheImage(
|
|
||||||
snapshot.data!.imageUrl,
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
fit: fit,
|
|
||||||
noErrorWidget: true,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
).paddingSymmetric(vertical: 4);
|
|
||||||
case 'attachments':
|
|
||||||
const radius = BorderRadius.all(Radius.circular(8));
|
|
||||||
return LimitedBox(
|
|
||||||
maxHeight: MediaQuery.of(context).size.width,
|
|
||||||
child: ClipRRect(
|
|
||||||
borderRadius: radius,
|
|
||||||
child: AttachmentSelfContainedEntry(
|
|
||||||
isDense: true,
|
|
||||||
parentId: parentId,
|
|
||||||
rid: segments[1],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
).paddingSymmetric(vertical: 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return AutoCacheImage(
|
|
||||||
url,
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
fit: fit,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (idx < paragraphs.length - 1) {
|
|
||||||
contentWidgets.add(isAutoWarp ? const Gap(4) : const Gap(8));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Return the list of widgets for the paragraphs
|
Widget _buildContent(BuildContext context) {
|
||||||
return Column(
|
var stickerIdx = 0;
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
return Markdown(
|
||||||
children: contentWidgets,
|
shrinkWrap: true,
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
data: widget.content,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
styleSheet: MarkdownStyleSheet.fromTheme(
|
||||||
|
Theme.of(context),
|
||||||
|
).copyWith(
|
||||||
|
textScaler: TextScaler.linear(widget.isLargeText ? 1.1 : 1),
|
||||||
|
blockquote: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
blockquoteDecoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
||||||
|
),
|
||||||
|
horizontalRuleDecoration: BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
top: BorderSide(
|
||||||
|
width: 1.0,
|
||||||
|
color: Theme.of(context).dividerColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
codeblockDecoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
color: Theme.of(context).dividerColor,
|
||||||
|
width: 0.3,
|
||||||
|
),
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
||||||
|
color: Theme.of(context).colorScheme.surface.withOpacity(0.5),
|
||||||
|
)),
|
||||||
|
builders: {
|
||||||
|
'code': _MarkdownTextCodeElement(),
|
||||||
|
},
|
||||||
|
softLineBreak: true,
|
||||||
|
extensionSet: markdown.ExtensionSet(
|
||||||
|
<markdown.BlockSyntax>[
|
||||||
|
markdown.CodeBlockSyntax(),
|
||||||
|
...markdown.ExtensionSet.commonMark.blockSyntaxes,
|
||||||
|
...markdown.ExtensionSet.gitHubFlavored.blockSyntaxes,
|
||||||
|
],
|
||||||
|
<markdown.InlineSyntax>[
|
||||||
|
if (widget.isAutoWarp) markdown.LineBreakSyntax(),
|
||||||
|
_UserNameCardInlineSyntax(),
|
||||||
|
_CustomEmoteInlineSyntax(),
|
||||||
|
markdown.AutolinkSyntax(),
|
||||||
|
markdown.AutolinkExtensionSyntax(),
|
||||||
|
markdown.CodeSyntax(),
|
||||||
|
...markdown.ExtensionSet.commonMark.inlineSyntaxes,
|
||||||
|
...markdown.ExtensionSet.gitHubFlavored.inlineSyntaxes
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTapLink: (text, href, title) async {
|
||||||
|
if (href == null) return;
|
||||||
|
if (href.startsWith('solink://')) {
|
||||||
|
final segments = href.replaceFirst('solink://', '').split('/');
|
||||||
|
switch (segments[0]) {
|
||||||
|
case 'users':
|
||||||
|
showModalBottomSheet(
|
||||||
|
useRootNavigator: true,
|
||||||
|
isScrollControlled: true,
|
||||||
|
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AccountProfilePopup(
|
||||||
|
name: segments[1],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await launchUrlString(
|
||||||
|
href,
|
||||||
|
mode: LaunchMode.externalApplication,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
imageBuilder: (uri, title, alt) {
|
||||||
|
var url = uri.toString();
|
||||||
|
double? width, height;
|
||||||
|
BoxFit? fit;
|
||||||
|
if (url.startsWith('solink://')) {
|
||||||
|
final segments = url.replaceFirst('solink://', '').split('/');
|
||||||
|
switch (segments[0]) {
|
||||||
|
case 'stickers':
|
||||||
|
double radius = 4;
|
||||||
|
final StickerProvider sticker = Get.find();
|
||||||
|
|
||||||
|
// Adjust sticker size based on the sticker count in this paragraph
|
||||||
|
width =
|
||||||
|
_stickerSizes.elementAtOrNull(stickerIdx)?.toDouble() ?? 16;
|
||||||
|
height =
|
||||||
|
_stickerSizes.elementAtOrNull(stickerIdx)?.toDouble() ?? 16;
|
||||||
|
if (width > 16) {
|
||||||
|
radius = 8;
|
||||||
|
}
|
||||||
|
stickerIdx++;
|
||||||
|
fit = BoxFit.contain;
|
||||||
|
return ClipRRect(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(radius)),
|
||||||
|
child: Container(
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||||
|
child: FutureBuilder(
|
||||||
|
future: sticker.getStickerByAlias(segments[1]),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (!snapshot.hasData) {
|
||||||
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
return AutoCacheImage(
|
||||||
|
snapshot.data!.imageUrl,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
fit: fit,
|
||||||
|
noErrorWidget: true,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).paddingSymmetric(vertical: 4);
|
||||||
|
case 'attachments':
|
||||||
|
final match = widget.attachments
|
||||||
|
?.where((x) => x.rid == segments[1])
|
||||||
|
.firstOrNull;
|
||||||
|
const radius = BorderRadius.all(Radius.circular(8));
|
||||||
|
if (match != null) {
|
||||||
|
final isImage =
|
||||||
|
match.mimetype.split('/').firstOrNull == 'image';
|
||||||
|
double ratio = match.metadata?['ratio']?.toDouble() ??
|
||||||
|
(isImage ? 1 : 16 / 9);
|
||||||
|
return LimitedBox(
|
||||||
|
maxWidth: 480,
|
||||||
|
maxHeight: 640,
|
||||||
|
child: AspectRatio(
|
||||||
|
aspectRatio: ratio,
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: radius,
|
||||||
|
child: AttachmentItem(
|
||||||
|
parentId: widget.parentId,
|
||||||
|
item: match,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).paddingSymmetric(vertical: 4);
|
||||||
|
} else {
|
||||||
|
return LimitedBox(
|
||||||
|
maxHeight: MediaQuery.of(context).size.width,
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: radius,
|
||||||
|
child: AttachmentSelfContainedEntry(
|
||||||
|
isDense: true,
|
||||||
|
parentId: widget.parentId,
|
||||||
|
rid: segments[1],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).paddingSymmetric(vertical: 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return AutoCacheImage(
|
||||||
|
url,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
fit: fit,
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (isSelectable) {
|
if (widget.isSelectable) {
|
||||||
return SelectionArea(child: _buildContent(context));
|
return SelectionArea(child: _buildContent(context));
|
||||||
}
|
}
|
||||||
return _buildContent(context);
|
return _buildContent(context);
|
||||||
|
@ -110,6 +110,7 @@ class _PostItemState extends State<PostItem> {
|
|||||||
child: MarkdownTextContent(
|
child: MarkdownTextContent(
|
||||||
parentId: 'p${item.id}',
|
parentId: 'p${item.id}',
|
||||||
content: item.body['content'],
|
content: item.body['content'],
|
||||||
|
attachments: item.preload?.attachments,
|
||||||
isAutoWarp: item.type == 'story',
|
isAutoWarp: item.type == 'story',
|
||||||
isSelectable: widget.isContentSelectable,
|
isSelectable: widget.isContentSelectable,
|
||||||
),
|
),
|
||||||
@ -131,21 +132,12 @@ class _PostItemState extends State<PostItem> {
|
|||||||
right: 8,
|
right: 8,
|
||||||
),
|
),
|
||||||
if (attachments.isNotEmpty)
|
if (attachments.isNotEmpty)
|
||||||
Row(
|
_PostAttachmentWidget(
|
||||||
children: [
|
item: item,
|
||||||
Icon(
|
padding: widget.padding,
|
||||||
Icons.file_copy,
|
isCompact: true,
|
||||||
size: 15,
|
isNonScrollAttachment: widget.isNonScrollAttachment,
|
||||||
color: _unFocusColor,
|
).paddingOnly(top: 4),
|
||||||
).paddingOnly(right: 5),
|
|
||||||
Text(
|
|
||||||
'attachmentHint'.trParams(
|
|
||||||
{'count': attachments.length.toString()},
|
|
||||||
),
|
|
||||||
style: TextStyle(color: _unFocusColor),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
).paddingOnly(left: 14, top: 4),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -173,6 +165,7 @@ class _PostItemState extends State<PostItem> {
|
|||||||
child: MarkdownTextContent(
|
child: MarkdownTextContent(
|
||||||
parentId: 'p${item.id}-embed',
|
parentId: 'p${item.id}-embed',
|
||||||
content: item.body['content'],
|
content: item.body['content'],
|
||||||
|
attachments: item.preload?.attachments,
|
||||||
isAutoWarp: item.type == 'story',
|
isAutoWarp: item.type == 'story',
|
||||||
isSelectable: widget.isContentSelectable,
|
isSelectable: widget.isContentSelectable,
|
||||||
),
|
),
|
||||||
@ -220,6 +213,7 @@ class _PostItemState extends State<PostItem> {
|
|||||||
_PostAttachmentWidget(
|
_PostAttachmentWidget(
|
||||||
item: item,
|
item: item,
|
||||||
padding: widget.padding,
|
padding: widget.padding,
|
||||||
|
isCompact: item.type == 'article',
|
||||||
isNonScrollAttachment: widget.isNonScrollAttachment,
|
isNonScrollAttachment: widget.isNonScrollAttachment,
|
||||||
),
|
),
|
||||||
if (widget.showFeaturedReply)
|
if (widget.showFeaturedReply)
|
||||||
@ -388,11 +382,13 @@ class _PostAttachmentWidget extends StatelessWidget {
|
|||||||
final Post item;
|
final Post item;
|
||||||
final EdgeInsets? padding;
|
final EdgeInsets? padding;
|
||||||
final bool isNonScrollAttachment;
|
final bool isNonScrollAttachment;
|
||||||
|
final bool isCompact;
|
||||||
|
|
||||||
const _PostAttachmentWidget({
|
const _PostAttachmentWidget({
|
||||||
required this.item,
|
required this.item,
|
||||||
required this.padding,
|
required this.padding,
|
||||||
required this.isNonScrollAttachment,
|
required this.isNonScrollAttachment,
|
||||||
|
this.isCompact = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -403,8 +399,32 @@ class _PostAttachmentWidget extends StatelessWidget {
|
|||||||
? List.from(item.body['attachments']?.whereType<String>())
|
? List.from(item.body['attachments']?.whereType<String>())
|
||||||
: List.empty();
|
: List.empty();
|
||||||
|
|
||||||
|
final unFocusColor =
|
||||||
|
Theme.of(context).colorScheme.onSurface.withOpacity(0.75);
|
||||||
|
|
||||||
if (attachments.isEmpty) return const SizedBox.shrink();
|
if (attachments.isEmpty) return const SizedBox.shrink();
|
||||||
|
|
||||||
|
if (isCompact) {
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.file_copy,
|
||||||
|
size: 13,
|
||||||
|
color: unFocusColor,
|
||||||
|
).paddingOnly(right: 5),
|
||||||
|
Text(
|
||||||
|
'attachmentHint'.trParams(
|
||||||
|
{'count': attachments.length.toString()},
|
||||||
|
),
|
||||||
|
style: TextStyle(color: unFocusColor, fontSize: 13),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
).paddingOnly(
|
||||||
|
left: (padding?.left ?? 0) + 17,
|
||||||
|
right: (padding?.right ?? 0) + 17,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (attachments.length == 1 && !isLargeScreen) {
|
if (attachments.length == 1 && !isLargeScreen) {
|
||||||
return AttachmentList(
|
return AttachmentList(
|
||||||
parentId: item.id.toString(),
|
parentId: item.id.toString(),
|
||||||
@ -422,7 +442,10 @@ class _PostAttachmentWidget extends StatelessWidget {
|
|||||||
attachments: item.preload?.attachments,
|
attachments: item.preload?.attachments,
|
||||||
autoload: false,
|
autoload: false,
|
||||||
isGrid: true,
|
isGrid: true,
|
||||||
).paddingSymmetric(horizontal: (padding?.horizontal ?? 0) + 14);
|
).paddingOnly(
|
||||||
|
left: (padding?.left ?? 0) + 14,
|
||||||
|
right: (padding?.right ?? 0) + 14,
|
||||||
|
);
|
||||||
} else if (attachments.length == 1 || isNonScrollAttachment) {
|
} else if (attachments.length == 1 || isNonScrollAttachment) {
|
||||||
return AttachmentList(
|
return AttachmentList(
|
||||||
parentId: item.id.toString(),
|
parentId: item.id.toString(),
|
||||||
@ -430,7 +453,10 @@ class _PostAttachmentWidget extends StatelessWidget {
|
|||||||
attachments: item.preload?.attachments,
|
attachments: item.preload?.attachments,
|
||||||
autoload: false,
|
autoload: false,
|
||||||
isColumn: true,
|
isColumn: true,
|
||||||
).paddingSymmetric(horizontal: (padding?.horizontal ?? 0) + 14);
|
).paddingOnly(
|
||||||
|
left: (padding?.left ?? 0) + 14,
|
||||||
|
right: (padding?.right ?? 0) + 14,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return AttachmentList(
|
return AttachmentList(
|
||||||
parentId: item.id.toString(),
|
parentId: item.id.toString(),
|
||||||
@ -526,7 +552,7 @@ class _PostHeaderDividerWidget extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (item.body['description'] != null || item.body['title'] != null) {
|
if (item.body['description'] != null || item.body['title'] != null) {
|
||||||
return const Gap(8);
|
return const SizedBox(height: 8);
|
||||||
}
|
}
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
|
@ -351,9 +351,9 @@ EXTERNAL SOURCES:
|
|||||||
:path: Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db
|
connectivity_plus: 4c41c08fc6d7c91f63bc7aec70ffe3730b04f563
|
||||||
desktop_drop: 69eeff437544aa619c8db7f4481b3a65f7696898
|
desktop_drop: 69eeff437544aa619c8db7f4481b3a65f7696898
|
||||||
device_info_plus: f1aae8670672f75c4c8850ecbe0b2ddef62b0a22
|
device_info_plus: 74e614483d05c89290d30a4c8feae15d555f7427
|
||||||
file_saver: 44e6fbf666677faf097302460e214e977fdd977b
|
file_saver: 44e6fbf666677faf097302460e214e977fdd977b
|
||||||
file_selector_macos: cc3858c981fe6889f364731200d6232dac1d812d
|
file_selector_macos: cc3858c981fe6889f364731200d6232dac1d812d
|
||||||
Firebase: 98e6bf5278170668a7983e12971a66b2cd57fc8c
|
Firebase: 98e6bf5278170668a7983e12971a66b2cd57fc8c
|
||||||
@ -386,7 +386,7 @@ SPEC CHECKSUMS:
|
|||||||
media_kit_native_event_loop: 81fd5b45192b72f8b5b69eaf5b540f45777eb8d5
|
media_kit_native_event_loop: 81fd5b45192b72f8b5b69eaf5b540f45777eb8d5
|
||||||
media_kit_video: c75b07f14d59706c775778e4dd47dd027de8d1e5
|
media_kit_video: c75b07f14d59706c775778e4dd47dd027de8d1e5
|
||||||
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
||||||
package_info_plus: d2f71247aab4b6521434f887276093acc70d214c
|
package_info_plus: f5790acc797bf17c3e959e9d6cf162cc68ff7523
|
||||||
pasteboard: 9b69dba6fedbb04866be632205d532fe2f6b1d99
|
pasteboard: 9b69dba6fedbb04866be632205d532fe2f6b1d99
|
||||||
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
|
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
|
||||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||||
@ -394,7 +394,7 @@ SPEC CHECKSUMS:
|
|||||||
protocol_handler_macos: d10a6c01d6373389ffd2278013ab4c47ed6d6daa
|
protocol_handler_macos: d10a6c01d6373389ffd2278013ab4c47ed6d6daa
|
||||||
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
||||||
screen_brightness_macos: 2d6d3af2165592d9a55ffcd95b7550970e41ebda
|
screen_brightness_macos: 2d6d3af2165592d9a55ffcd95b7550970e41ebda
|
||||||
share_plus: a182a58e04e51647c0481aadabbc4de44b3a2bce
|
share_plus: fd717ef89a2801d3491e737630112b80c310640e
|
||||||
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
|
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
|
||||||
sqflite_darwin: a553b1fd6fe66f53bbb0fe5b4f5bab93f08d7a13
|
sqflite_darwin: a553b1fd6fe66f53bbb0fe5b4f5bab93f08d7a13
|
||||||
sqlite3: 0bb0e6389d824e40296f531b858a2a0b71c0d2fb
|
sqlite3: 0bb0e6389d824e40296f531b858a2a0b71c0d2fb
|
||||||
|
96
pubspec.lock
96
pubspec.lock
@ -254,14 +254,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.18.0"
|
version: "1.18.0"
|
||||||
|
confetti:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: confetti
|
||||||
|
sha256: "79376a99648efbc3f23582f5784ced0fe239922bd1a0fb41f582051eba750751"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.8.0"
|
||||||
connectivity_plus:
|
connectivity_plus:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: connectivity_plus
|
name: connectivity_plus
|
||||||
sha256: "2056db5241f96cdc0126bd94459fc4cdc13876753768fc7a31c425e50a7177d0"
|
sha256: "876849631b0c7dc20f8b471a2a03142841b482438e3b707955464f5ffca3e4c3"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.0.5"
|
version: "6.1.0"
|
||||||
connectivity_plus_platform_interface:
|
connectivity_plus_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -274,10 +282,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: convert
|
name: convert
|
||||||
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
|
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.1"
|
version: "3.1.2"
|
||||||
cross_file:
|
cross_file:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -290,10 +298,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: crypto
|
name: crypto
|
||||||
sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27
|
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.5"
|
version: "3.0.6"
|
||||||
csslib:
|
csslib:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -338,10 +346,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: device_info_plus
|
name: device_info_plus
|
||||||
sha256: db03b2d2a3fa466a4627709e1db58692c3f7f658e36a5942d342d86efedc4091
|
sha256: c4af09051b4f0508f6c1dc0a5c085bf014d5c9a4a0678ce1799c2b4d716387a0
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "11.0.0"
|
version: "11.1.0"
|
||||||
device_info_plus_platform_interface:
|
device_info_plus_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -378,26 +386,26 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: drift
|
name: drift
|
||||||
sha256: d6ff1ec6a0f3fa097dda6b776cf601f1f3d88b53b287288e09c1306f394fb1b3
|
sha256: df027d168a2985a2e9da900adeba2ab0136f0d84436592cf3cd5135f82c8579c
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.20.3"
|
version: "2.21.0"
|
||||||
drift_dev:
|
drift_dev:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: drift_dev
|
name: drift_dev
|
||||||
sha256: "3ee987578ca2281b5ff91eadd757cd6dd36001458d6e33784f990d67ff38f756"
|
sha256: "27bab15e7869b69259663590381180117873b9b273a1ea9ebb21bb73133d1233"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.20.3"
|
version: "2.21.0"
|
||||||
drift_flutter:
|
drift_flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: drift_flutter
|
name: drift_flutter
|
||||||
sha256: c670c947fe17ad149678a43fdbbfdb69321f0c83d315043e34e8ad2729e11f49
|
sha256: fec503e9d408f36bb345f9f6d24bc9d62b7b5f970db49760253d9e8d3acd48d5
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.0"
|
version: "0.2.1"
|
||||||
dropdown_button2:
|
dropdown_button2:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -618,10 +626,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: fixnum
|
name: fixnum
|
||||||
sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1"
|
sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.1"
|
||||||
fl_chart:
|
fl_chart:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1049,10 +1057,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: image
|
name: image
|
||||||
sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8"
|
sha256: f31d52537dc417fdcde36088fdf11d191026fd5e4fae742491ebd40e5a8bea7d
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.2.0"
|
version: "4.3.0"
|
||||||
image_cropper:
|
image_cropper:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1089,26 +1097,26 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: image_picker_android
|
name: image_picker_android
|
||||||
sha256: d3e5e00fdfeca8fd4ffb3227001264d449cc8950414c2ff70b0e06b9c628e643
|
sha256: d34e0d9e024e81321b2aeed7b202ec6181cc282e6a1c0c0b4e6ad07ef1065d82
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.12+15"
|
version: "0.8.12+16"
|
||||||
image_picker_for_web:
|
image_picker_for_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: image_picker_for_web
|
name: image_picker_for_web
|
||||||
sha256: "65d94623e15372c5c51bebbcb820848d7bcb323836e12dfdba60b5d3a8b39e50"
|
sha256: "717eb042ab08c40767684327be06a5d8dbb341fe791d514e4b92c7bbe1b7bb83"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.5"
|
version: "3.0.6"
|
||||||
image_picker_ios:
|
image_picker_ios:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: image_picker_ios
|
name: image_picker_ios
|
||||||
sha256: "6703696ad49f5c3c8356d576d7ace84d1faf459afb07accbb0fae780753ff447"
|
sha256: "4f0568120c6fcc0aaa04511cb9f9f4d29fc3d0139884b1d06be88dcec7641d6b"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.12"
|
version: "0.8.12+1"
|
||||||
image_picker_linux:
|
image_picker_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1249,10 +1257,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: logging
|
name: logging
|
||||||
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
|
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.3.0"
|
||||||
macos_window_utils:
|
macos_window_utils:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1393,10 +1401,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: mime
|
name: mime
|
||||||
sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a"
|
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.6"
|
version: "2.0.0"
|
||||||
nested:
|
nested:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1433,10 +1441,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: package_info_plus
|
name: package_info_plus
|
||||||
sha256: "894f37107424311bdae3e476552229476777b8752c5a2a2369c0cb9a2d5442ef"
|
sha256: df3eb3e0aed5c1107bb0fdb80a8e82e778114958b1c5ac5644fb1ac9cae8a998
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.0.3"
|
version: "8.1.0"
|
||||||
package_info_plus_platform_interface:
|
package_info_plus_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1529,10 +1537,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: permission_handler_android
|
name: permission_handler_android
|
||||||
sha256: "76e4ab092c1b240d31177bb64d2b0bea43f43d0e23541ec866151b9f7b2490fa"
|
sha256: "71bbecfee799e65aff7c744761a57e817e73b738fedf62ab7afd5593da21f9f1"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "12.0.12"
|
version: "12.0.13"
|
||||||
permission_handler_apple:
|
permission_handler_apple:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1577,10 +1585,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: platform
|
name: platform
|
||||||
sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65"
|
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.5"
|
version: "3.1.6"
|
||||||
platform_detect:
|
platform_detect:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1825,10 +1833,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: share_plus
|
name: share_plus
|
||||||
sha256: fec12c3c39f01e4df1ec6ad92b6e85503c5ca64ffd6e28d18c9ffe53fcc4cb11
|
sha256: "334fcdf0ef9c0df0e3b428faebcac9568f35c747d59831474b2fc56e156d244e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.0.3"
|
version: "10.1.0"
|
||||||
share_plus_platform_interface:
|
share_plus_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -2014,10 +2022,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: sqlparser
|
name: sqlparser
|
||||||
sha256: "852cf80f9e974ac8e1b613758a8aa640215f7701352b66a7f468e95711eb570b"
|
sha256: c5f63dff8677407ddcddfa4744c176ea6dc44286c47ba9e69e76d8071398034d
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.38.1"
|
version: "0.39.1"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -2118,10 +2126,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: typed_data
|
name: typed_data
|
||||||
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
|
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.2"
|
version: "1.4.0"
|
||||||
universal_io:
|
universal_io:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -2206,10 +2214,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_windows
|
name: url_launcher_windows
|
||||||
sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185"
|
sha256: "44cf3aabcedde30f2dba119a9dea3b0f2672fbe6fa96e85536251d678216b3c4"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.2"
|
version: "3.1.3"
|
||||||
uuid:
|
uuid:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -2342,10 +2350,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: win32
|
name: win32
|
||||||
sha256: e5c39a90447e7c81cfec14b041cdbd0d0916bd9ebbc7fe02ab69568be703b9bd
|
sha256: "2294c64768987ea280b43a3d8357d42d5679f3e2b5b69b602be45b2abbd165b0"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.6.0"
|
version: "5.6.1"
|
||||||
win32_registry:
|
win32_registry:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -2,7 +2,7 @@ name: solian
|
|||||||
description: "The Solar Network App"
|
description: "The Solar Network App"
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
|
|
||||||
version: 1.4.0+16
|
version: 1.4.0+17
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.3.4 <4.0.0"
|
sdk: ">=3.3.4 <4.0.0"
|
||||||
@ -90,6 +90,7 @@ dependencies:
|
|||||||
flutter_resizable_container: ^3.0.0
|
flutter_resizable_container: ^3.0.0
|
||||||
file_saver: ^0.2.14
|
file_saver: ^0.2.14
|
||||||
marquee: ^2.3.0
|
marquee: ^2.3.0
|
||||||
|
confetti: ^0.8.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user