Compare commits

...

4 Commits

Author SHA1 Message Date
de39799301 🚀 Launch 1.2.3 2024-09-22 22:57:00 +08:00
4b921602a2 🐛 Bug fixes 2024-09-22 22:56:28 +08:00
6cde218393 💄 Optimization of post item style 2024-09-21 23:28:14 +08:00
c896185af0 See other user recent fortune 2024-09-21 23:10:20 +08:00
13 changed files with 506 additions and 336 deletions

View File

@@ -433,6 +433,7 @@
"updateCheckStrictly": "Strict mode",
"updateCheckStrictlyDesc": "If enabled, the app will ask for updating once the local version is different from remote one.",
"updateMayAvailable": "App version @version is available, you can update from app store or our website.",
"updateNow": "Update now",
"termAccept": "I've read and agree to Solar Network's Terms",
"termAcceptDesc": "Including but not limited to \"User Agreement\" and \"Privacy Policy\"",
"termAcceptLink": "View terms",

View File

@@ -428,6 +428,7 @@
"update": "更新",
"updateCheckStrictly": "严格模式",
"updateCheckStrictlyDesc": "如果启用,应用程序将会在本地版本与远程版本不同时询问更新,而不会检查版本号大小。",
"updateNow": "立即更新",
"updateMayAvailable": "版本 @version 现已可用,你可以前往应用商店或是我们的官网下载更新。",
"termAccept": "我已阅读并同意 Solar Network 各项条款",
"termAcceptDesc": "包括但不限于《用户守则》和《隐私政策》",

View File

@@ -227,7 +227,7 @@ PODS:
- TOCropViewController (~> 2.7.4)
- image_picker_ios (0.0.1):
- Flutter
- livekit_client (2.2.5):
- livekit_client (2.2.6):
- Flutter
- WebRTC-SDK (= 125.6422.04)
- media_kit_libs_ios_video (1.0.4):
@@ -482,7 +482,7 @@ SPEC CHECKSUMS:
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
image_cropper: 37d40f62177c101ff4c164906d259ea2c3aa70cf
image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
livekit_client: 9c8080879256a0fb16da13c9be4845248209d896
livekit_client: 20e01637431bc108dad451c8a11c1d206e1dd2cd
media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1
media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a
media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e

View File

@@ -42,6 +42,28 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
final Completer _bootCompleter = Completer();
void _updateNow(String localVersionString, String remoteVersionString) {
context
.showConfirmDialog(
'updateAvailable'.tr,
'updateAvailableDesc'.trParams({
'from': localVersionString,
'to': remoteVersionString,
}),
)
.then((result) {
if (result) {
final model = UpdateModel(
'https://files.solsynth.dev/d/production01/solian/app-arm64-v8a-release.apk',
'solian-app-arm64-v8a-release.apk',
'ic_launcher',
'https://testflight.apple.com/join/YJ0lmN6O',
);
AzhonAppUpdate.update(model);
}
});
}
Future<void> _checkForUpdate() async {
if (PlatformInfo.isWeb) return;
try {
@@ -70,25 +92,7 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
remoteBuildNumber > localBuildNumber) ||
(remoteVersionString != localVersionString && strictUpdate)) {
if (PlatformInfo.isAndroid) {
context
.showConfirmDialog(
'updateAvailable'.tr,
'updateAvailableDesc'.trParams({
'from': localVersionString,
'to': remoteVersionString,
}),
)
.then((result) {
if (result) {
final model = UpdateModel(
'https://files.solsynth.dev/d/production01/solian/app-arm64-v8a-release.apk',
'solian-app-arm64-v8a-release.apk',
'ic_launcher',
'https://testflight.apple.com/join/YJ0lmN6O',
);
AzhonAppUpdate.update(model);
}
});
_updateNow(localVersionString, remoteVersionString);
} else {
context.showInfoDialog(
'updateAvailable'.tr,
@@ -97,9 +101,19 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
}
} else if (remoteVersionString != localVersionString) {
_bootCompleter.future.then((_) {
context.showSnackbar('updateMayAvailable'.trParams({
'version': remoteVersionString,
}));
context.showSnackbar(
'updateMayAvailable'.trParams({
'version': remoteVersionString,
}),
action: PlatformInfo.isAndroid
? SnackBarAction(
label: 'updateNow'.tr,
onPressed: () {
_updateNow(localVersionString, remoteVersionString);
},
)
: null,
);
});
}
} catch (e) {

View File

@@ -1,11 +1,16 @@
import 'dart:math';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:get/get.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
import 'package:intl/intl.dart';
import 'package:solian/controllers/post_list_controller.dart';
import 'package:solian/exts.dart';
import 'package:solian/models/account.dart';
import 'package:solian/models/attachment.dart';
import 'package:solian/models/daily_sign.dart';
import 'package:solian/models/pagination.dart';
import 'package:solian/models/post.dart';
import 'package:solian/models/subscription.dart';
@@ -18,6 +23,7 @@ import 'package:solian/widgets/account/account_avatar.dart';
import 'package:solian/widgets/account/account_heading.dart';
import 'package:solian/widgets/app_bar_leading.dart';
import 'package:solian/widgets/attachments/attachment_list.dart';
import 'package:solian/widgets/daily_sign/history_chart.dart';
import 'package:solian/widgets/posts/post_list.dart';
import 'package:solian/widgets/posts/post_warped_list.dart';
import 'package:solian/widgets/sized_container.dart';
@@ -45,6 +51,7 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
Account? _userinfo;
Subscription? _subscription;
List<Post> _pinnedPosts = List.empty();
List<DailySignRecord> _dailySignRecords = List.empty();
int _totalUpvote = 0, _totalDownvote = 0;
Future<void> _getSubscription() async {
@@ -57,7 +64,7 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
Future<void> _getUserinfo() async {
setState(() => _isBusy = true);
var client = await ServiceFinder.configureClient('auth');
var client = await ServiceFinder.configureClient('id');
var resp = await client.get('/users/${widget.name}');
if (resp.statusCode != 200) {
context.showErrorDialog(resp.bodyString).then((_) {
@@ -67,7 +74,7 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
_userinfo = Account.fromJson(resp.body);
}
client = await ServiceFinder.configureClient('interactive');
client = await ServiceFinder.configureClient('co');
resp = await client.get('/users/${widget.name}');
if (resp.statusCode != 200) {
context.showErrorDialog(resp.bodyString).then((_) {
@@ -82,7 +89,7 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
}
Future<void> _getPinnedPosts() async {
final client = await ServiceFinder.configureClient('interactive');
final client = await ServiceFinder.configureClient('co');
final resp = await client.get('/users/${widget.name}/pin');
if (resp.statusCode != 200) {
context.showErrorDialog(resp.bodyString).then((_) {
@@ -96,6 +103,23 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
}
}
Future<void> _getDailySignRecords() async {
final client = await ServiceFinder.configureClient('id');
final resp = await client.get('/users/${widget.name}/daily?take=14');
if (resp.statusCode != 200) {
context.showErrorDialog(resp.bodyString).then((_) {
Navigator.pop(context);
});
} else {
final result = PaginationResult.fromJson(resp.body);
setState(() {
_dailySignRecords = List.from(
result.data?.map((x) => DailySignRecord.fromJson(x)) ?? [],
);
});
}
}
int get _userSocialCreditPoints {
return _totalUpvote * 2 - _totalDownvote + _postController.postTotal.value;
}
@@ -129,6 +153,7 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
_getUserinfo().then((_) {
_getSubscription();
_getPinnedPosts();
_getDailySignRecords();
});
}
@@ -168,96 +193,99 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
toolbarHeight: AppTheme.toolbarHeight(context),
leadingWidth: 24,
automaticallyImplyLeading: false,
flexibleSpace: Row(
children: [
AppBarLeadingButton.adaptive(context) ?? const Gap(8),
const Gap(8),
if (_userinfo != null)
AccountAvatar(content: _userinfo!.avatar, radius: 16),
const Gap(12),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (_userinfo != null)
Text(
_userinfo!.nick,
style: Theme.of(context).textTheme.bodyLarge,
),
if (_userinfo != null)
Text(
'@${_userinfo!.name}',
style: Theme.of(context).textTheme.bodySmall,
),
],
),
),
if (_userinfo != null && _subscription == null)
OutlinedButton(
style: const ButtonStyle(
visualDensity:
VisualDensity(horizontal: -4, vertical: -2),
flexibleSpace: SizedBox(
height: 56,
child: Row(
children: [
AppBarLeadingButton.adaptive(context) ?? const Gap(8),
const Gap(8),
if (_userinfo != null)
AccountAvatar(content: _userinfo!.avatar, radius: 16),
const Gap(12),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (_userinfo != null)
Text(
_userinfo!.nick,
style: Theme.of(context).textTheme.bodyLarge,
),
if (_userinfo != null)
Text(
'@${_userinfo!.name}',
style: Theme.of(context).textTheme.bodySmall,
),
],
),
onPressed: _isSubscribing
? null
: () async {
setState(() => _isSubscribing = true);
_subscription =
await Get.find<SubscriptionProvider>()
.subscribeToUser(_userinfo!.id);
setState(() => _isSubscribing = false);
},
child: Text('subscribe'.tr),
)
else if (_userinfo != null)
OutlinedButton(
style: const ButtonStyle(
visualDensity:
VisualDensity(horizontal: -4, vertical: -2),
),
if (_userinfo != null && _subscription == null)
OutlinedButton(
style: const ButtonStyle(
visualDensity:
VisualDensity(horizontal: -4, vertical: -2),
),
onPressed: _isSubscribing
? null
: () async {
setState(() => _isSubscribing = true);
_subscription =
await Get.find<SubscriptionProvider>()
.subscribeToUser(_userinfo!.id);
setState(() => _isSubscribing = false);
},
child: Text('subscribe'.tr),
)
else if (_userinfo != null)
OutlinedButton(
style: const ButtonStyle(
visualDensity:
VisualDensity(horizontal: -4, vertical: -2),
),
onPressed: _isSubscribing
? null
: () async {
setState(() => _isSubscribing = true);
await Get.find<SubscriptionProvider>()
.unsubscribeFromUser(_userinfo!.id);
_subscription = null;
setState(() => _isSubscribing = false);
},
child: Text('unsubscribe'.tr),
),
onPressed: _isSubscribing
? null
: () async {
setState(() => _isSubscribing = true);
await Get.find<SubscriptionProvider>()
.unsubscribeFromUser(_userinfo!.id);
_subscription = null;
setState(() => _isSubscribing = false);
},
child: Text('unsubscribe'.tr),
if (_userinfo != null &&
!_relationshipProvider.hasFriend(_userinfo!))
IconButton(
icon: const Icon(Icons.person_add),
onPressed: _isMakingFriend
? null
: () async {
setState(() => _isMakingFriend = true);
try {
await _relationshipProvider
.makeFriend(widget.name);
context.showSnackbar(
'accountFriendRequestSent'.tr,
);
} catch (e) {
context.showErrorDialog(e);
} finally {
setState(() => _isMakingFriend = false);
}
},
)
else
const IconButton(
icon: Icon(Icons.handshake),
onPressed: null,
),
SizedBox(
width: AppTheme.isLargeScreen(context) ? 8 : 16,
),
if (_userinfo != null &&
!_relationshipProvider.hasFriend(_userinfo!))
IconButton(
icon: const Icon(Icons.person_add),
onPressed: _isMakingFriend
? null
: () async {
setState(() => _isMakingFriend = true);
try {
await _relationshipProvider
.makeFriend(widget.name);
context.showSnackbar(
'accountFriendRequestSent'.tr,
);
} catch (e) {
context.showErrorDialog(e);
} finally {
setState(() => _isMakingFriend = false);
}
},
)
else
const IconButton(
icon: Icon(Icons.handshake),
onPressed: null,
),
SizedBox(
width: AppTheme.isLargeScreen(context) ? 8 : 16,
),
],
),
],
),
).paddingOnly(top: MediaQuery.of(context).padding.top),
bottom: TabBar(
tabs: [
Tab(text: 'profilePage'.tr),
@@ -271,21 +299,132 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
body: TabBarView(
physics: const NeverScrollableScrollPhysics(),
children: [
Column(
ListView(
children: [
const Gap(16),
AccountHeadingWidget(
name: _userinfo!.name,
nick: _userinfo!.nick,
desc: _userinfo!.description,
badges: _userinfo!.badges,
banner: _userinfo!.banner,
avatar: _userinfo!.avatar,
status: Get.find<StatusProvider>()
.getSomeoneStatus(_userinfo!.name),
detail: _userinfo,
profile: _userinfo!.profile,
extraWidgets: const [],
CenteredContainer(
child: AccountHeadingWidget(
name: _userinfo!.name,
nick: _userinfo!.nick,
desc: _userinfo!.description,
badges: _userinfo!.badges,
banner: _userinfo!.banner,
avatar: _userinfo!.avatar,
status: Get.find<StatusProvider>()
.getSomeoneStatus(_userinfo!.name),
detail: _userinfo,
profile: _userinfo!.profile,
extraWidgets: [
if (_dailySignRecords.isNotEmpty)
Card(
child: SizedBox(
height: 180,
width:
max(640, MediaQuery.of(context).size.width),
child: LineChart(
LineChartData(
lineBarsData: [
LineChartBarData(
isCurved: true,
isStrokeCapRound: true,
isStrokeJoinRound: true,
color:
Theme.of(context).colorScheme.primary,
belowBarData: BarAreaData(
show: true,
gradient: LinearGradient(
colors: List.filled(
_dailySignRecords.length,
Theme.of(context)
.colorScheme
.primary
.withOpacity(0.3),
).toList(),
),
),
spots: _dailySignRecords
.map(
(x) => FlSpot(
x.createdAt
.copyWith(
hour: 0,
minute: 0,
second: 0,
millisecond: 0,
microsecond: 0,
)
.millisecondsSinceEpoch
.toDouble(),
x.resultTier.toDouble(),
),
)
.toList(),
)
],
lineTouchData: LineTouchData(
touchTooltipData: LineTouchTooltipData(
getTooltipItems: (spots) => spots
.map((spot) => LineTooltipItem(
'${DailySignHistoryChartDialog.signSymbols[spot.y.toInt()]}\n${DateFormat('MM/dd').format(DateTime.fromMillisecondsSinceEpoch(spot.x.toInt()))}',
TextStyle(
color: Theme.of(context)
.colorScheme
.onSurface,
),
))
.toList(),
getTooltipColor: (_) => Theme.of(context)
.colorScheme
.surfaceContainerHigh,
),
),
titlesData: FlTitlesData(
topTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
rightTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
leftTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 40,
interval: 1,
getTitlesWidget: (value, _) => Align(
alignment: Alignment.centerRight,
child: Text(
DailySignHistoryChartDialog
.signSymbols[value.toInt()],
textAlign: TextAlign.right,
).paddingOnly(right: 8),
),
),
),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 28,
interval: 86400000,
getTitlesWidget: (value, _) => Text(
DateFormat('dd').format(
DateTime.fromMillisecondsSinceEpoch(
value.toInt(),
),
),
textAlign: TextAlign.center,
).paddingOnly(top: 8),
),
),
),
gridData: const FlGridData(show: false),
borderData: FlBorderData(show: false),
),
),
).marginOnly(
right: 24, left: 12, bottom: 8, top: 24),
)
],
),
),
],
),
@@ -373,8 +512,9 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
),
CenteredContainer(
child: RefreshIndicator(
onRefresh: () =>
Future.sync(() => _albumPagingController.refresh()),
onRefresh: () => Future.sync(
() => _albumPagingController.refresh(),
),
child: PagedGridView<int, Attachment>(
padding: EdgeInsets.zero,
pagingController: _albumPagingController,

View File

@@ -88,7 +88,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
Future<void> _pullDaily() async {
try {
_signRecord = await _dailySign.getToday();
_dailySign.listLastRecord(30).then((value) {
_dailySign.listLastRecord(14).then((value) {
setState(() => _signRecordHistory = value);
});
} catch (e) {
@@ -103,7 +103,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
try {
_signRecord = await _dailySign.signToday();
_dailySign.listLastRecord(30).then((value) {
_dailySign.listLastRecord(14).then((value) {
setState(() => _signRecordHistory = value);
});
} catch (e) {

View File

@@ -21,6 +21,7 @@ class AttachmentItem extends StatefulWidget {
final bool showBadge;
final bool showHideButton;
final bool autoload;
final bool isDense;
final BoxFit fit;
final String? badge;
final Function? onHide;
@@ -34,6 +35,7 @@ class AttachmentItem extends StatefulWidget {
this.showBadge = true,
this.showHideButton = true,
this.autoload = false,
this.isDense = false,
this.onHide,
});
@@ -53,6 +55,7 @@ class _AttachmentItemState extends State<AttachmentItem> {
fit: widget.fit,
showBadge: widget.showBadge,
showHideButton: widget.showHideButton,
isDense: widget.isDense,
onHide: widget.onHide,
);
case 'video':
@@ -120,6 +123,7 @@ class _AttachmentItemImage extends StatelessWidget {
final bool showBadge;
final bool showHideButton;
final BoxFit fit;
final bool isDense;
final String? badge;
final Function? onHide;
@@ -128,6 +132,7 @@ class _AttachmentItemImage extends StatelessWidget {
required this.item,
required this.showBadge,
required this.showHideButton,
required this.isDense,
required this.fit,
this.badge,
this.onHide,
@@ -146,6 +151,7 @@ class _AttachmentItemImage extends StatelessWidget {
'/attachments/${item.rid}',
),
fit: fit,
isDense: isDense,
),
if (showBadge && badge != null)
Positioned(

View File

@@ -338,6 +338,7 @@ class AttachmentListEntry extends StatelessWidget {
badge: showBadge ? badgeContent : null,
showHideButton: !item!.isMature || showMature,
autoload: autoload,
isDense: isDense,
onHide: () {
onReveal(false);
},

View File

@@ -12,7 +12,7 @@ class DailySignHistoryChartDialog extends StatelessWidget {
const DailySignHistoryChartDialog({super.key, required this.data});
static List<String> signSymbols = ['大凶', '', '中平', '', '大吉'];
static final List<String> signSymbols = ['大凶', '', '中平', '', '大吉'];
DateTime? get _firstRecordDate => data?.map((x) => x.createdAt).reduce(
(a, b) => DateTime.fromMillisecondsSinceEpoch(
@@ -42,215 +42,222 @@ class DailySignHistoryChartDialog extends StatelessWidget {
child: CircularProgressIndicator(),
),
)
: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'dailySignHistoryRecent'.tr,
style: Theme.of(context).textTheme.titleMedium,
).paddingOnly(bottom: 18),
SizedBox(
height: 180,
width: max(640, MediaQuery.of(context).size.width),
child: LineChart(
LineChartData(
lineBarsData: [
LineChartBarData(
isCurved: true,
isStrokeCapRound: true,
isStrokeJoinRound: true,
color: Theme.of(context).colorScheme.primary,
belowBarData: BarAreaData(
show: true,
gradient: LinearGradient(
colors: List.filled(
data!.length,
Theme.of(context)
.colorScheme
.primary
.withOpacity(0.3),
).toList(),
),
),
spots: data!
.map(
(x) => FlSpot(
x.createdAt
.copyWith(
hour: 0,
minute: 0,
second: 0,
millisecond: 0,
microsecond: 0,
)
.millisecondsSinceEpoch
.toDouble(),
x.resultTier.toDouble(),
),
)
.toList(),
)
],
lineTouchData: LineTouchData(
touchTooltipData: LineTouchTooltipData(
getTooltipItems: (spots) => spots
.map((spot) => LineTooltipItem(
'${signSymbols[spot.y.toInt()]}\n${DateFormat('MM/dd').format(DateTime.fromMillisecondsSinceEpoch(spot.x.toInt()))}',
TextStyle(
color:
Theme.of(context).colorScheme.onSurface,
),
))
.toList(),
getTooltipColor: (_) =>
Theme.of(context).colorScheme.surfaceContainerHigh,
)),
titlesData: FlTitlesData(
topTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
rightTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
leftTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 40,
interval: 1,
getTitlesWidget: (value, _) => Align(
alignment: Alignment.centerRight,
child: Text(
signSymbols[value.toInt()],
textAlign: TextAlign.right,
).paddingOnly(right: 8),
),
),
),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 28,
interval: 86400000,
getTitlesWidget: (value, _) => Text(
DateFormat('dd').format(
DateTime.fromMillisecondsSinceEpoch(
value.toInt(),
),
: SizedBox(
width: double.maxFinite,
child: ListView(
shrinkWrap: true,
children: [
Text(
'dailySignHistoryRecent'.tr,
style: Theme.of(context).textTheme.titleMedium,
).paddingOnly(bottom: 18),
SizedBox(
height: 180,
width: max(640, MediaQuery.of(context).size.width),
child: LineChart(
LineChartData(
lineBarsData: [
LineChartBarData(
isCurved: true,
isStrokeCapRound: true,
isStrokeJoinRound: true,
color: Theme.of(context).colorScheme.primary,
belowBarData: BarAreaData(
show: true,
gradient: LinearGradient(
colors: List.filled(
data!.length,
Theme.of(context)
.colorScheme
.primary
.withOpacity(0.3),
).toList(),
),
textAlign: TextAlign.center,
).paddingOnly(top: 8),
),
),
),
gridData: const FlGridData(show: false),
borderData: FlBorderData(show: false),
),
),
).marginOnly(right: 24, bottom: 8, top: 8),
const Gap(16),
Text(
'dailySignHistoryReward'.tr,
style: Theme.of(context).textTheme.titleMedium,
).paddingOnly(bottom: 18),
SizedBox(
height: 180,
width: max(640, MediaQuery.of(context).size.width),
child: LineChart(
LineChartData(
lineBarsData: [
LineChartBarData(
isCurved: true,
isStrokeCapRound: true,
isStrokeJoinRound: true,
color: Theme.of(context).colorScheme.primary,
belowBarData: BarAreaData(
show: true,
gradient: LinearGradient(
colors: List.filled(
data!.length,
Theme.of(context)
.colorScheme
.primary
.withOpacity(0.3),
).toList(),
),
),
spots: data!
.map(
(x) => FlSpot(
x.createdAt
.copyWith(
hour: 0,
minute: 0,
second: 0,
millisecond: 0,
microsecond: 0,
)
.millisecondsSinceEpoch
.toDouble(),
x.resultExperience.toDouble(),
),
)
.toList(),
)
],
lineTouchData: LineTouchData(
touchTooltipData: LineTouchTooltipData(
getTooltipItems: (spots) => spots
.map((spot) => LineTooltipItem(
'+${spot.y.toStringAsFixed(0)} EXP\n${DateFormat('MM/dd').format(DateTime.fromMillisecondsSinceEpoch(spot.x.toInt()))}',
TextStyle(
color:
Theme.of(context).colorScheme.onSurface,
spots: data!
.map(
(x) => FlSpot(
x.createdAt
.copyWith(
hour: 0,
minute: 0,
second: 0,
millisecond: 0,
microsecond: 0,
)
.millisecondsSinceEpoch
.toDouble(),
x.resultTier.toDouble(),
),
))
.toList(),
getTooltipColor: (_) =>
Theme.of(context).colorScheme.surfaceContainerHigh,
)),
titlesData: FlTitlesData(
topTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
)
.toList(),
)
],
lineTouchData: LineTouchData(
touchTooltipData: LineTouchTooltipData(
getTooltipItems: (spots) => spots
.map((spot) => LineTooltipItem(
'${signSymbols[spot.y.toInt()]}\n${DateFormat('MM/dd').format(DateTime.fromMillisecondsSinceEpoch(spot.x.toInt()))}',
TextStyle(
color: Theme.of(context)
.colorScheme
.onSurface,
),
))
.toList(),
getTooltipColor: (_) => Theme.of(context)
.colorScheme
.surfaceContainerHigh,
),
),
rightTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
leftTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 40,
getTitlesWidget: (value, _) => Align(
alignment: Alignment.centerRight,
child: Text(
value.toStringAsFixed(0),
textAlign: TextAlign.right,
).paddingOnly(right: 8),
titlesData: FlTitlesData(
topTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
rightTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
leftTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 40,
interval: 1,
getTitlesWidget: (value, _) => Align(
alignment: Alignment.centerRight,
child: Text(
signSymbols[value.toInt()],
textAlign: TextAlign.right,
).paddingOnly(right: 8),
),
),
),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 28,
interval: 86400000,
getTitlesWidget: (value, _) => Text(
DateFormat('dd').format(
DateTime.fromMillisecondsSinceEpoch(
value.toInt(),
),
),
textAlign: TextAlign.center,
).paddingOnly(top: 8),
),
),
),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 28,
interval: 86400000,
getTitlesWidget: (value, _) => Text(
DateFormat('dd').format(
DateTime.fromMillisecondsSinceEpoch(
value.toInt(),
),
gridData: const FlGridData(show: false),
borderData: FlBorderData(show: false),
),
),
).marginOnly(right: 24, bottom: 8, top: 8),
const Gap(16),
Text(
'dailySignHistoryReward'.tr,
style: Theme.of(context).textTheme.titleMedium,
).paddingOnly(bottom: 18),
SizedBox(
height: 180,
width: max(640, MediaQuery.of(context).size.width),
child: LineChart(
LineChartData(
lineBarsData: [
LineChartBarData(
isCurved: true,
isStrokeCapRound: true,
isStrokeJoinRound: true,
color: Theme.of(context).colorScheme.primary,
belowBarData: BarAreaData(
show: true,
gradient: LinearGradient(
colors: List.filled(
data!.length,
Theme.of(context)
.colorScheme
.primary
.withOpacity(0.3),
).toList(),
),
textAlign: TextAlign.center,
).paddingOnly(top: 8),
),
spots: data!
.map(
(x) => FlSpot(
x.createdAt
.copyWith(
hour: 0,
minute: 0,
second: 0,
millisecond: 0,
microsecond: 0,
)
.millisecondsSinceEpoch
.toDouble(),
x.resultExperience.toDouble(),
),
)
.toList(),
)
],
lineTouchData: LineTouchData(
touchTooltipData: LineTouchTooltipData(
getTooltipItems: (spots) => spots
.map((spot) => LineTooltipItem(
'+${spot.y.toStringAsFixed(0)} EXP\n${DateFormat('MM/dd').format(DateTime.fromMillisecondsSinceEpoch(spot.x.toInt()))}',
TextStyle(
color: Theme.of(context)
.colorScheme
.onSurface,
),
))
.toList(),
getTooltipColor: (_) => Theme.of(context)
.colorScheme
.surfaceContainerHigh,
)),
titlesData: FlTitlesData(
topTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
rightTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
leftTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 40,
getTitlesWidget: (value, _) => Align(
alignment: Alignment.centerRight,
child: Text(
value.toStringAsFixed(0),
textAlign: TextAlign.right,
).paddingOnly(right: 8),
),
),
),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 28,
interval: 86400000,
getTitlesWidget: (value, _) => Text(
DateFormat('dd').format(
DateTime.fromMillisecondsSinceEpoch(
value.toInt(),
),
),
textAlign: TextAlign.center,
).paddingOnly(top: 8),
),
),
),
gridData: const FlGridData(show: false),
borderData: FlBorderData(show: false),
),
gridData: const FlGridData(show: false),
borderData: FlBorderData(show: false),
),
),
).marginOnly(right: 24, bottom: 8, top: 8),
],
).marginOnly(right: 24, bottom: 8, top: 8),
],
),
),
);
}

View File

@@ -313,7 +313,7 @@ class _PostItemState extends State<PostItem> {
attachmentsId: attachments,
autoload: false,
isColumn: true,
).paddingOnly(left: 60, right: 24);
).paddingOnly(left: 60, right: 24, top: 4, bottom: 4);
} else {
return AttachmentList(
flatMaxHeight: MediaQuery.of(context).size.width,

View File

@@ -158,7 +158,7 @@ PODS:
- GoogleUtilities/UserDefaults (8.0.2):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- livekit_client (2.2.5):
- livekit_client (2.2.6):
- FlutterMacOS
- WebRTC-SDK (= 125.6422.04)
- macos_window_utils (1.0.0):
@@ -359,7 +359,7 @@ SPEC CHECKSUMS:
GoogleAppMeasurement: 6e49ffac7d3f2c3ded9cc663f912a13b67bbd0de
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
livekit_client: be04a950a4b84b9dbc87507ffad5154fe75fa067
livekit_client: 98d09566e3a936b3402be8091ec3845556d36800
macos_window_utils: 933f91f64805e2eb91a5bd057cf97cd097276663
media_kit_libs_macos_video: b3e2bbec2eef97c285f2b1baa7963c67c753fb82
media_kit_native_event_loop: 81fd5b45192b72f8b5b69eaf5b540f45777eb8d5

View File

@@ -751,10 +751,10 @@ packages:
dependency: "direct dev"
description:
name: flutter_launcher_icons
sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea"
sha256: a38f2f1b3c373d42bf08bd17d60e20d3c73abce7727607b4d085ec7d5acaa294
url: "https://pub.dev"
source: hosted
version: "0.13.1"
version: "0.14.0"
flutter_lints:
dependency: "direct dev"
description:

View File

@@ -2,7 +2,7 @@ name: solian
description: "The Solar Network App"
publish_to: "none"
version: 1.2.2+3
version: 1.2.3+1
environment:
sdk: ">=3.3.4 <4.0.0"
@@ -89,7 +89,7 @@ dev_dependencies:
sdk: flutter
flutter_lints: ^4.0.0
flutter_launcher_icons: ^0.13.1
flutter_launcher_icons: ^0.14.0
build_runner: ^2.4.12
flutter_native_splash: ^2.4.1