mirror of
https://github.com/simon-ding/polaris.git
synced 2026-06-02 07:57:45 +08:00
feat: seperate active and archived activities
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"polaris/ent"
|
"polaris/ent"
|
||||||
"polaris/ent/episode"
|
"polaris/ent/episode"
|
||||||
|
"polaris/ent/history"
|
||||||
"polaris/log"
|
"polaris/log"
|
||||||
"polaris/pkg/utils"
|
"polaris/pkg/utils"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -18,9 +19,16 @@ type Activity struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) GetAllActivities(c *gin.Context) (interface{}, error) {
|
func (s *Server) GetAllActivities(c *gin.Context) (interface{}, error) {
|
||||||
|
q := c.Query("status")
|
||||||
his := s.db.GetHistories()
|
his := s.db.GetHistories()
|
||||||
var activities = make([]Activity, 0, len(his))
|
var activities = make([]Activity, 0, len(his))
|
||||||
for _, h := range his {
|
for _, h := range his {
|
||||||
|
if q == "active" && (h.Status != history.StatusRunning && h.Status != history.StatusUploading) {
|
||||||
|
continue //active downloads
|
||||||
|
} else if q == "archive" && (h.Status == history.StatusRunning || h.Status == history.StatusUploading) {
|
||||||
|
continue //archived downloads
|
||||||
|
}
|
||||||
|
|
||||||
a := Activity{
|
a := Activity{
|
||||||
History: h,
|
History: h,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,13 +5,58 @@ import 'package:ui/providers/activity.dart';
|
|||||||
import 'package:ui/utils.dart';
|
import 'package:ui/utils.dart';
|
||||||
import 'package:ui/widgets/progress_indicator.dart';
|
import 'package:ui/widgets/progress_indicator.dart';
|
||||||
|
|
||||||
class ActivityPage extends ConsumerWidget {
|
class ActivityPage extends ConsumerStatefulWidget {
|
||||||
|
const ActivityPage({super.key});
|
||||||
static const route = "/activities";
|
static const route = "/activities";
|
||||||
|
|
||||||
const ActivityPage({super.key});
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
_ActivityPageState createState() => _ActivityPageState();
|
||||||
var activitiesWatcher = ref.watch(activitiesDataProvider);
|
}
|
||||||
|
|
||||||
|
class _ActivityPageState extends ConsumerState<ActivityPage>
|
||||||
|
with TickerProviderStateMixin {
|
||||||
|
late TabController _nestedTabController;
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_nestedTabController = new TabController(length: 2, vsync: this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
_nestedTabController.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
int selectedTab = 0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
TabBar(
|
||||||
|
controller: _nestedTabController,
|
||||||
|
isScrollable: true,
|
||||||
|
onTap: (value) {
|
||||||
|
setState(() {
|
||||||
|
selectedTab = value;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
tabs: const <Widget>[
|
||||||
|
Tab(
|
||||||
|
text: "下载中",
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
text: "历史记录",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Builder(builder: (context) {
|
||||||
|
var activitiesWatcher = ref.watch(activitiesDataProvider("active"));
|
||||||
|
if (selectedTab == 1) {
|
||||||
|
activitiesWatcher = ref.watch(activitiesDataProvider("archive"));
|
||||||
|
}
|
||||||
|
|
||||||
return activitiesWatcher.when(
|
return activitiesWatcher.when(
|
||||||
data: (activities) {
|
data: (activities) {
|
||||||
@@ -26,18 +71,22 @@ class ActivityPage extends ConsumerWidget {
|
|||||||
DataColumn(label: Text("操作"))
|
DataColumn(label: Text("操作"))
|
||||||
],
|
],
|
||||||
source: ActivityDataSource(
|
source: ActivityDataSource(
|
||||||
activities: activities, onDelete: onDelete(ref)),
|
activities: activities,
|
||||||
|
onDelete: selectedTab == 0 ? onDelete() : null),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
error: (err, trace) => Text("$err"),
|
error: (err, trace) => Text("$err"),
|
||||||
loading: () => const MyProgressIndicator());
|
loading: () => const MyProgressIndicator());
|
||||||
|
})
|
||||||
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Function(int) onDelete(WidgetRef ref) {
|
Function(int) onDelete() {
|
||||||
return (id) {
|
return (id) {
|
||||||
ref
|
ref
|
||||||
.read(activitiesDataProvider.notifier)
|
.read(activitiesDataProvider("active").notifier)
|
||||||
.deleteActivity(id)
|
.deleteActivity(id)
|
||||||
.whenComplete(() => Utils.showSnakeBar("删除成功"))
|
.whenComplete(() => Utils.showSnakeBar("删除成功"))
|
||||||
.onError((error, trace) => Utils.showSnakeBar("删除失败:$error"));
|
.onError((error, trace) => Utils.showSnakeBar("删除失败:$error"));
|
||||||
@@ -47,8 +96,8 @@ class ActivityPage extends ConsumerWidget {
|
|||||||
|
|
||||||
class ActivityDataSource extends DataTableSource {
|
class ActivityDataSource extends DataTableSource {
|
||||||
List<Activity> activities;
|
List<Activity> activities;
|
||||||
Function(int) onDelete;
|
Function(int)? onDelete;
|
||||||
ActivityDataSource({required this.activities, required this.onDelete});
|
ActivityDataSource({required this.activities, this.onDelete});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get rowCount => activities.length;
|
int get rowCount => activities.length;
|
||||||
@@ -96,11 +145,13 @@ class ActivityDataSource extends DataTableSource {
|
|||||||
progressColor: Colors.green,
|
progressColor: Colors.green,
|
||||||
);
|
);
|
||||||
}()),
|
}()),
|
||||||
DataCell(Tooltip(
|
onDelete != null
|
||||||
|
? DataCell(Tooltip(
|
||||||
message: "删除任务",
|
message: "删除任务",
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
onPressed: () => onDelete(activity.id!),
|
onPressed: () => onDelete!(activity.id!),
|
||||||
icon: const Icon(Icons.delete))))
|
icon: const Icon(Icons.delete))))
|
||||||
|
: const DataCell(Text(""))
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import 'package:ui/providers/APIs.dart';
|
|||||||
import 'package:ui/providers/server_response.dart';
|
import 'package:ui/providers/server_response.dart';
|
||||||
|
|
||||||
var activitiesDataProvider =
|
var activitiesDataProvider =
|
||||||
AsyncNotifierProvider.autoDispose<ActivityData, List<Activity>>(
|
AsyncNotifierProvider.autoDispose.family<ActivityData, List<Activity>, String>(
|
||||||
ActivityData.new);
|
ActivityData.new);
|
||||||
|
|
||||||
var mediaHistoryDataProvider = FutureProvider.autoDispose.family(
|
var mediaHistoryDataProvider = FutureProvider.autoDispose.family(
|
||||||
@@ -24,14 +24,18 @@ var mediaHistoryDataProvider = FutureProvider.autoDispose.family(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
class ActivityData extends AutoDisposeAsyncNotifier<List<Activity>> {
|
class ActivityData
|
||||||
|
extends AutoDisposeFamilyAsyncNotifier<List<Activity>, String> {
|
||||||
@override
|
@override
|
||||||
FutureOr<List<Activity>> build() async {
|
FutureOr<List<Activity>> build(String arg) async {
|
||||||
Timer(
|
if (arg == "active") {
|
||||||
const Duration(seconds: 5), ref.invalidateSelf); //Periodically Refresh
|
//refresh active downloads
|
||||||
|
Timer(const Duration(seconds: 5),
|
||||||
|
ref.invalidateSelf); //Periodically Refresh
|
||||||
|
}
|
||||||
|
|
||||||
final dio = await APIs.getDio();
|
final dio = await APIs.getDio();
|
||||||
var resp = await dio.get(APIs.activityUrl);
|
var resp = await dio.get(APIs.activityUrl, queryParameters: {"status": arg});
|
||||||
final sp = ServerResponse.fromJson(resp.data);
|
final sp = ServerResponse.fromJson(resp.data);
|
||||||
if (sp.code != 0) {
|
if (sp.code != 0) {
|
||||||
throw sp.message;
|
throw sp.message;
|
||||||
|
|||||||
Reference in New Issue
Block a user