Skip to content

Commit

Permalink
feat: add refresh button & parse dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
simon-ding committed Nov 1, 2024
1 parent 2da02fa commit e67413c
Show file tree
Hide file tree
Showing 8 changed files with 291 additions and 59 deletions.
28 changes: 28 additions & 0 deletions server/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@ func (s *Server) DownloadAll(c *gin.Context) (interface{}, error) {
if err != nil {
return nil, errors.Wrap(err, "convert")
}
return s.downloadAllEpisodes(id)
}

func (s *Server) downloadAllEpisodes(id int) (interface{}, error) {
m, err := s.db.GetMedia(id)
if err != nil {
return nil, errors.Wrap(err, "get media")
Expand All @@ -186,3 +190,27 @@ func (s *Server) DownloadAll(c *gin.Context) (interface{}, error) {

return []string{name}, err
}

func (s *Server) DownloadAllTv(c *gin.Context) (interface{}, error) {
tvs := s.db.GetMediaWatchlist(media.MediaTypeTv)
var allNames []string
for _, tv := range tvs {
names, err := s.downloadAllEpisodes(tv.ID)
if err == nil {
allNames = append(allNames, names.([]string)...)
}
}
return allNames, nil
}

func (s *Server) DownloadAllMovies(c *gin.Context) (interface{}, error) {
movies := s.db.GetMediaWatchlist(media.MediaTypeMovie)
var allNames []string
for _, mv := range movies {
names, err := s.downloadAllEpisodes(mv.ID)
if err == nil {
allNames = append(allNames, names.([]string)...)
}
}
return allNames, nil
}
2 changes: 2 additions & 0 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ func (s *Server) Serve() error {
tv.GET("/suggest/tv/:tmdb_id", HttpHandler(s.SuggestedSeriesFolderName))
tv.GET("/suggest/movie/:tmdb_id", HttpHandler(s.SuggestedMovieFolderName))
tv.GET("/downloadall/:id", HttpHandler(s.DownloadAll))
tv.GET("/download/tv", HttpHandler(s.DownloadAllTv))
tv.GET("/download/movie", HttpHandler(s.DownloadAllMovies))
}
indexer := api.Group("/indexer")
{
Expand Down
1 change: 1 addition & 0 deletions server/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ func (s *Server) SetSetting(c *gin.Context) (interface{}, error) {
return nil, nil
}


func (s *Server) GetSetting(c *gin.Context) (interface{}, error) {
tmdb := s.db.GetSetting(db.SettingTmdbApiKey)
downloadDir := s.db.GetSetting(db.SettingDownloadDir)
Expand Down
56 changes: 55 additions & 1 deletion ui/lib/providers/APIs.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
Expand All @@ -8,9 +10,12 @@ class APIs {
static final _baseUrl = baseUrl();
static final searchUrl = "$_baseUrl/api/v1/media/search";
static final editMediaUrl = "$_baseUrl/api/v1/media/edit";
static final downloadAllUrl = "$_baseUrl/api/v1/media/downloadall/";
static final downloadAllEpisodesUrl = "$_baseUrl/api/v1/media/downloadall/";
static final downloadAllTvUrl = "$_baseUrl/api/v1/media/download/tv";
static final downloadAllMovieUrl = "$_baseUrl/api/v1/media/download/movie";
static final settingsUrl = "$_baseUrl/api/v1/setting/do";
static final settingsGeneralUrl = "$_baseUrl/api/v1/setting/general";
//static final singleSettingUrl = "$_baseUrl/api/v1/setting/";
static final watchlistTvUrl = "$_baseUrl/api/v1/media/tv/watchlist";
static final watchlistMovieUrl = "$_baseUrl/api/v1/media/movie/watchlist";
static final availableTorrentsUrl = "$_baseUrl/api/v1/media/torrents/";
Expand Down Expand Up @@ -50,6 +55,9 @@ class APIs {

static final cronJobUrl = "$_baseUrl/api/v1/setting/cron/trigger";

static final tvParseUrl = "$_baseUrl/api/v1/setting/parse/tv";
static final movieParseUrl = "$_baseUrl/api/v1/setting/parse/movie";

static const tmdbApiKey = "tmdb_api_key";
static const downloadDirKey = "download_dir";

Expand Down Expand Up @@ -114,4 +122,50 @@ class APIs {
throw sp.message;
}
}

static Future<List<String>> downloadAllTv() async {
var resp = await getDio().get(APIs.downloadAllTvUrl);

var sp = ServerResponse.fromJson(resp.data);

if (sp.code != 0) {
throw sp.message;
}
return sp.data as List<String>;
}

static Future<List<String>> downloadAllMovies() async {
var resp = await getDio().get(APIs.downloadAllMovieUrl);

var sp = ServerResponse.fromJson(resp.data);

if (sp.code != 0) {
throw sp.message;
}
return sp.data as List<String>;
}

static Future<String> parseTvName(String s) async {
var resp = await getDio().post(APIs.tvParseUrl, data: {"s": s});

var sp = ServerResponse.fromJson(resp.data);

if (sp.code != 0) {
throw sp.message;
}
JsonEncoder encoder = new JsonEncoder.withIndent(' ');
return encoder.convert(sp.data);
}

static Future<String> parseMovieName(String s) async {
var resp = await getDio().post(APIs.movieParseUrl, data: {"s": s});

var sp = ServerResponse.fromJson(resp.data);

if (sp.code != 0) {
throw sp.message;
}
JsonEncoder encoder = new JsonEncoder.withIndent(' ');
return encoder.convert(sp.data);
}
}
2 changes: 1 addition & 1 deletion ui/lib/providers/series_details.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class SeriesDetailData

Future<dynamic> downloadall() async {
final dio = APIs.getDio();
var resp = await dio.get(APIs.downloadAllUrl + id!);
var resp = await dio.get(APIs.downloadAllEpisodesUrl + id!);
var sp = ServerResponse.fromJson(resp.data);
if (sp.code != 0) {
throw sp.message;
Expand Down
2 changes: 1 addition & 1 deletion ui/lib/providers/settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ var prowlarrSettingDataProvider =
class EditSettingData extends AutoDisposeAsyncNotifier<GeneralSetting> {
@override
FutureOr<GeneralSetting> build() async {
final dio = await APIs.getDio();
final dio = APIs.getDio();

var resp = await dio.get(APIs.settingsGeneralUrl);
var rrr = ServerResponse.fromJson(resp.data);
Expand Down
202 changes: 149 additions & 53 deletions ui/lib/welcome_page.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:ui/movie_watchlist.dart';
import 'package:ui/providers/APIs.dart';
import 'package:ui/providers/welcome_data.dart';
import 'package:ui/tv_details.dart';
import 'package:ui/widgets/progress_indicator.dart';
import 'package:ui/widgets/utils.dart';
import 'package:ui/widgets/widgets.dart';

class WelcomePage extends ConsumerStatefulWidget {
const WelcomePage({super.key});
Expand All @@ -20,7 +23,7 @@ class WelcomePage extends ConsumerStatefulWidget {

class WelcomePageState extends ConsumerState<WelcomePage> {
//WelcomePageState({super.key});

final _formKey = GlobalKey<FormBuilderState>();
bool onlyShowUnfinished = false;

@override
Expand Down Expand Up @@ -50,66 +53,94 @@ class WelcomePageState extends ConsumerState<WelcomePage> {
_ => const MyProgressIndicator(),
};
}(),
Row(
getMoreButtonAndActions(uri)
],
);
}

Widget getMoreButtonAndActions(String uri) {
return Row(
children: [
Expanded(child: Container()),
Column(
children: [
Expanded(child: Container()),
Column(
children: [
Expanded(child: Container()),
Padding(
padding: EdgeInsets.all(20),
child: MenuAnchor(
style: MenuStyle(
//minimumSize: WidgetStatePropertyAll(Size(400, 300)),

backgroundColor: WidgetStatePropertyAll(Theme.of(context)
.colorScheme
.inversePrimary
.withOpacity(0.9)),
),
menuChildren: [
MenuItemButton(
onPressed: null,
child: CheckboxListTile(
value: onlyShowUnfinished,
onChanged: (b) {
setState(() {
onlyShowUnfinished = b!;
});
},
title: const Text(
"未完成",
style: TextStyle(fontSize: 16),
softWrap: false,
),
controlAffinity: ListTileControlAffinity.leading,
),
),
],
builder: (context, controller, child) {
return Opacity(
opacity: 0.7,
child: FloatingActionButton(
onPressed: () {
if (controller.isOpen) {
controller.close();
} else {
controller.open();
}
},
child: const Icon(Icons.more_horiz),
));
},
),
Padding(
padding: EdgeInsets.all(20),
child: MenuAnchor(
style: MenuStyle(
alignment: Alignment.topLeft,
backgroundColor: WidgetStatePropertyAll(Theme.of(context)
.colorScheme
.inversePrimary
.withOpacity(0.7)),
),
],
)
menuChildren: [parseName(), onlyUnfinished(), refreshAll(uri)],
builder: (context, controller, child) {
return Opacity(
opacity: 0.7,
child: FloatingActionButton(
onPressed: () {
if (controller.isOpen) {
controller.close();
} else {
controller.open();
}
},
child: const Icon(Icons.more_horiz),
));
},
),
),
],
),
)
],
);
}

Widget onlyUnfinished() {
return CheckboxListTile(
value: onlyShowUnfinished,
onChanged: (b) {
setState(() {
onlyShowUnfinished = b!;
});
},
title: const Text(
"未完成",
style: TextStyle(fontSize: 16),
softWrap: false,
),
controlAffinity: ListTileControlAffinity.leading,
);
}

Widget refreshAll(String uri) {
return LoadingListTile(
icon: Icons.refresh,
text: "全部更新",
onPressed: () async {
if (uri == WelcomePage.routeMoivie) {
await APIs.downloadAllMovies().then((v) {
showSnakeBar("开始下载电影:$v");
});
} else {
await APIs.downloadAllTv().then((v) {
showSnakeBar("开始下载剧集:$v");
});
}
},
);
}

Widget parseName() {
return ListTile(
leading: Icon(Icons.calculate),
title: Text("测试解析"),
onTap: () => _showNameParsingDialog(),
);
}

bool isSmallScreen(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
return screenWidth < 600;
Expand All @@ -135,6 +166,71 @@ class WelcomePageState extends ConsumerState<WelcomePage> {
return MediaCard(item: item);
});
}

Future<void> _showNameParsingDialog() async {
final resultController = TextEditingController();
return showDialog<void>(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('测试名称解析'),
content: SizedBox(
width: 500,
height: 400,
child: FormBuilder(
key: _formKey,
initialValue: {"name": "", "type": "tv"},
child: Column(
children: [
FormBuilderTextField(
name: "name",
decoration: InputDecoration(labelText: "要解析的名字"),
),
FormBuilderDropdown(
name: "type",
items: [
DropdownMenuItem(
value: "tv",
child: const Text("电视剧"),
),
DropdownMenuItem(value: "movie", child: const Text("电影"))
],
),
Center(
child: Padding(
padding: EdgeInsets.all(10),
child: LoadingTextButton(
onPressed: () async {
if (_formKey.currentState!.saveAndValidate()) {
final values = _formKey.currentState!.value;
//print(values);
if (values["type"] == "tv") {
var s = await APIs.parseTvName(values["name"]);
resultController.text = s;
} else {
var s =
await APIs.parseMovieName(values["name"]);
resultController.text = s;
}
}
return;
},
label: Text("解析")),
),
),
TextField(
maxLines: 8,
controller: resultController,
)
],
),
),
),
);
},
);
}
}

class MediaCard extends StatelessWidget {
Expand Down
Loading

0 comments on commit e67413c

Please sign in to comment.