Compare commits

...

2 Commits

Author SHA1 Message Date
d764b042fe Shows account own activities on account page 2025-11-02 16:59:58 +08:00
a76b97d1d2 💄 Shows listening activities are from spotfiy 2025-11-02 16:55:16 +08:00
2 changed files with 246 additions and 188 deletions

View File

@@ -8,6 +8,7 @@ import 'package:island/pods/userinfo.dart';
import 'package:island/screens/notification.dart';
import 'package:island/services/responsive.dart';
import 'package:island/widgets/account/account_name.dart';
import 'package:island/widgets/account/activity_presence.dart';
import 'package:island/widgets/account/status.dart';
import 'package:island/widgets/account/leveling_progress.dart';
import 'package:island/widgets/alert.dart';
@@ -177,7 +178,21 @@ class AccountScreen extends HookConsumerWidget {
).padding(horizontal: 8),
Card(
margin: EdgeInsets.zero,
child: AccountStatusCreationWidget(uname: user.value!.name),
child: Column(
children: [
AccountStatusCreationWidget(uname: user.value!.name),
ActivityPresenceWidget(
uname: user.value!.name,
isCompact: true,
compactPadding: const EdgeInsets.only(
left: 16,
right: 16,
bottom: 8,
top: 4,
),
),
],
),
).padding(horizontal: 12, bottom: 4),
LevelingProgressCard(
isCompact: true,
@@ -251,7 +266,9 @@ class AccountScreen extends HookConsumerWidget {
).padding(horizontal: 12),
const SizedBox.shrink(),
ConstrainedBox(
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width),
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width,
),
child: LayoutBuilder(
builder: (context, constraints) {
const minWidth = 160.0;
@@ -312,14 +329,23 @@ class AccountScreen extends HookConsumerWidget {
if (availableWidth > totalMin) {
return Row(
spacing: 8,
children: children.map((child) => Expanded(child: child)).toList(),
children:
children
.map((child) => Expanded(child: child))
.toList(),
).padding(horizontal: 12).height(48);
} else {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
spacing: 8,
children: children.map((child) => SizedBox(width: minWidth, child: child)).toList(),
children:
children
.map(
(child) =>
SizedBox(width: minWidth, child: child),
)
.toList(),
).padding(horizontal: 12),
).height(48);
}

View File

@@ -393,9 +393,11 @@ class _ActivityPresenceWidgetState extends State<ActivityPresenceWidget>
],
).opacity(0.75).padding(horizontal: 16, bottom: 8),
...activities.map((activity) {
final dcImages = _buildImages(ref, activity);
final images = _buildImages(ref, activity);
return Card(
return Stack(
children: [
Card(
elevation: 0,
shape: RoundedRectangleBorder(
side: BorderSide(
@@ -409,11 +411,12 @@ class _ActivityPresenceWidgetState extends State<ActivityPresenceWidget>
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (dcImages.isNotEmpty)
if (images.isNotEmpty)
Row(
crossAxisAlignment: CrossAxisAlignment.end,
crossAxisAlignment:
CrossAxisAlignment.end,
spacing: 8,
children: dcImages,
children: images,
).padding(vertical: 4),
Row(
spacing: 2,
@@ -431,7 +434,9 @@ class _ActivityPresenceWidgetState extends State<ActivityPresenceWidget>
onPressed: () {
launchUrlString(activity.titleUrl!);
},
icon: const Icon(Symbols.launch_rounded),
icon: const Icon(
Symbols.launch_rounded,
),
iconSize: 16,
padding: EdgeInsets.all(4),
constraints: const BoxConstraints(
@@ -468,11 +473,13 @@ class _ActivityPresenceWidgetState extends State<ActivityPresenceWidget>
builder: (context, snapshot) {
final now = DateTime.now();
final meta =
activity.meta as Map<String, dynamic>;
activity.meta
as Map<String, dynamic>;
final progressMs =
meta['progress_ms'] as int? ?? 0;
final durationMs =
meta['track_duration_ms'] as int? ?? 1;
meta['track_duration_ms'] as int? ??
1;
final elapsed =
now
.difference(activity.createdAt)
@@ -488,7 +495,9 @@ class _ActivityPresenceWidgetState extends State<ActivityPresenceWidget>
begin: _startProgress,
end: _endProgress,
).animate(_progressController);
_progressController.forward(from: 0.0);
_progressController.forward(
from: 0.0,
);
}
return AnimatedBuilder(
animation: _progressAnimation,
@@ -503,7 +512,8 @@ class _ActivityPresenceWidgetState extends State<ActivityPresenceWidget>
final currentSec =
(animatedProgressMs % 60000) ~/
1000;
final totalMin = durationMs ~/ 60000;
final totalMin =
durationMs ~/ 60000;
final totalSec =
(durationMs % 60000) ~/ 1000;
return Column(
@@ -516,11 +526,12 @@ class _ActivityPresenceWidgetState extends State<ActivityPresenceWidget>
backgroundColor:
Colors.grey.shade300,
trackGap: 0,
stopIndicatorColor: Colors.green,
valueColor:
AlwaysStoppedAnimation<Color>(
stopIndicatorColor:
Colors.green,
),
valueColor:
AlwaysStoppedAnimation<
Color
>(Colors.green),
).padding(top: 3),
Text(
'${currentMin.toString().padLeft(2, '0')}:${currentSec.toString().padLeft(2, '0')} / ${totalMin.toString().padLeft(2, '0')}:${totalSec.toString().padLeft(2, '0')}',
@@ -549,10 +560,12 @@ class _ActivityPresenceWidgetState extends State<ActivityPresenceWidget>
final hours = duration.inHours
.toString()
.padLeft(2, '0');
final minutes = (duration.inMinutes % 60)
final minutes = (duration.inMinutes %
60)
.toString()
.padLeft(2, '0');
final seconds = (duration.inSeconds % 60)
final seconds = (duration.inSeconds %
60)
.toString()
.padLeft(2, '0');
return Text(
@@ -564,12 +577,16 @@ class _ActivityPresenceWidgetState extends State<ActivityPresenceWidget>
Row(
spacing: 2,
children: [
Flexible(child: Text(activity.subtitle!)),
Flexible(
child: Text(activity.subtitle!),
),
if (activity.titleUrl != null &&
activity.titleUrl!.isNotEmpty)
IconButton(
onPressed: () {
launchUrlString(activity.titleUrl!);
launchUrlString(
activity.titleUrl!,
);
},
icon: const Icon(
Symbols.launch_rounded,
@@ -588,7 +605,22 @@ class _ActivityPresenceWidgetState extends State<ActivityPresenceWidget>
],
),
),
).padding(horizontal: 8);
).padding(horizontal: 8),
if (activity.manualId == 'spotify')
Positioned(
top: 16,
right: 24,
child: Tooltip(
message: 'Listening on Spotify',
child: Image.asset(
'assets/images/oidc/spotify.png',
width: 24,
height: 24,
),
),
),
],
);
}),
],
).padding(horizontal: 8, top: 8, bottom: 16),