Skip to content

Commit

Permalink
wip: add rss support
Browse files Browse the repository at this point in the history
  • Loading branch information
brainwo committed Apr 28, 2024
1 parent 1e93357 commit 918387a
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 7 deletions.
12 changes: 12 additions & 0 deletions lib/const.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,15 @@ const String defaultThemeName = 'Arc-Dark';
const String searchModeVideoShortcut = 'v ';
const String searchModeChannelShortcut = 'c ';
const String searchModePlaylistShortcut = 'p ';

const List<String> configPathLookup = [
'/yatta/config.yaml',
'/yatta/config.yml',
'/yatta/config.json',
];

const List<String> feedPathLookup = [
'/yatta/feed.yaml',
'/yatta/feed.yml',
'/yatta/feed.json',
];
2 changes: 2 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'model/config.dart';
import 'model/setting_options.dart';
import 'model/state.dart';
import 'model/theme.dart';
import 'page/feed.dart';
import 'page/history.dart';
import 'page/home.dart';
import 'page/playlist.dart';
Expand Down Expand Up @@ -147,6 +148,7 @@ class App extends StatelessWidget {
routes: {
'/': (final _) => const HomePage(),
'/playlist': (final _) => const PlaylistPage(),
'/feed': (final _) => const FeedPage(),
'/history': (final _) => const HistoryPage(),
'/settings': (final _) => const SettingsPage(),
},
Expand Down
7 changes: 1 addition & 6 deletions lib/model/config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,9 @@ import 'package:xdg_directories/xdg_directories.dart';
import 'package:yaml/yaml.dart';
import 'package:yaml_edit/yaml_edit.dart';

import '../const.dart';
import 'setting_options.dart';

const List<String> configPathLookup = [
'/yatta/config.yaml',
'/yatta/config.yml',
'/yatta/config.json',
];

abstract class YamlConfig {
YamlConfig({
final String? filePath,
Expand Down
144 changes: 144 additions & 0 deletions lib/page/feed.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import 'dart:async';
import 'dart:io';

import 'package:autoscroll/autoscroll.dart';
import 'package:collection/collection.dart';
import 'package:fluent_ui/fluent_ui.dart';
import 'package:http/http.dart' as http;
import 'package:rss_dart/dart_rss.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:xdg_directories/xdg_directories.dart' as xdg;
import 'package:yaml/yaml.dart' as yaml;
import 'package:youtube_api/youtube_api.dart';

import '../../intent.dart';
import '../const.dart';
import '../helper/command_parser.dart';
import '../widget/keyboard_navigation.dart';
import '../widget/list_items/list_item.dart';

class FeedPage extends StatefulWidget {
const FeedPage({super.key});

@override
State<FeedPage> createState() => _FeedPageState();
}

class _FeedPageState extends State<FeedPage> {
final FocusNode searchBarFocus = FocusNode();
List<AtomItem>? filteredList;
List<AtomItem>? feedList;
late final Map<Type, Action<Intent>> _actionMap = {
SearchBarFocusIntent: CallbackAction<Intent>(
onInvoke: (final _) => _requestSearchBarFocus(),
),
NavigationPopIntent: CallbackAction<Intent>(
onInvoke: (final _) => _navigationPop(context),
)
};

@override
void initState() {
super.initState();

WidgetsBinding.instance.addPostFrameCallback((final _) async {
await fetchFeed();
});
}

Future<void> fetchFeed() async {
final file = feedPathLookup
.map((final path) => File('${xdg.configHome.path}$path'))
.firstWhereOrNull((final configLookup) => configLookup.existsSync());

if (file == null) return;

final result = await file
.readAsString()
.then((final rawFile) => switch (yaml.loadYaml(rawFile)) {
final List<dynamic> urls => urls
.map((final url) => http.get(Uri.parse(url.toString())))
.toList(),
_ => <Future<http.Response>>[]
})
.then((final urls) async => Future.wait(urls));

setState(() {
feedList = result
.map((final e) => AtomFeed.parse(e.body))
.expand((final e) => e.items)
.sorted((final a, final b) => DateTime.parse(a.published ?? '')
.compareTo(DateTime.parse(b.published ?? '')))
.toList();

filteredList = feedList;
});
}

void _requestSearchBarFocus() => searchBarFocus.requestFocus();

void _navigationPop(final BuildContext context) {
if (!Navigator.of(context).canPop()) return;
Navigator.of(context).pop();
}

void _filterList(final String keyword) {
if (filteredList == null) return;
setState(() {
filteredList = feedList
?.where((final e) =>
e.toString().toLowerCase().contains(keyword.toLowerCase()))
.toList();
});
}

@override
Widget build(final BuildContext context) {
return Actions(
actions: _actionMap,
child: NavigationView(
appBar: NavigationAppBar(
title: SizedBox(
height: 36,
child: TextBox(
focusNode: searchBarFocus,
placeholder: 'Search from feed',
onChanged: _filterList,
),
),
),
content: KeyboardNavigation(
child: AutoscrollListView.builder(
itemCount: filteredList?.length ?? 0,
itemBuilder: (final context, final index) {
final youtubeVideo =
filteredList![filteredList!.length - index - 1];
// print(youtubeVideo
// .items.first.media?.group?.);

final listItem = ListItemVideo(
title: youtubeVideo.media?.title?.value ?? '',
channelTitle: youtubeVideo.authors.first.name ?? '',
description:
youtubeVideo.media?.group?.description?.value ?? '',
duration: '00:02',
thumbnailUrl:
youtubeVideo.media?.group?.thumbnail.firstOrNull?.url ?? '',
publishedAt: youtubeVideo.published ?? '',
);

return listItem;

return ListItem(
autofocus: index == 0,
youtubeVideo: YoutubeVideo(''),
fromHistory: true,
child: listItem,
);
},
),
),
),
);
}
}
4 changes: 3 additions & 1 deletion lib/page/home.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ class WelcomeMessage extends StatelessWidget {
title: 'Feed',
subtitle: 'Subsribe to channels via RSS Feed',
icon: FluentIcons.content_feed,
onPressed: () {},
onPressed: () async {
await Navigator.of(context).pushNamed('/feed');
},
),
_SelectionMenu(
key: const Key('history'),
Expand Down
23 changes: 23 additions & 0 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.2.1"
petitparser:
dependency: transitive
description:
name: petitparser
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
url: "https://pub.dev"
source: hosted
version: "6.0.2"
platform:
dependency: transitive
description:
Expand Down Expand Up @@ -516,6 +524,13 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.10"
rss_dart:
dependency: "direct main"
description:
path: "../rss.dart"
relative: true
source: path
version: "1.0.6"
rxdart:
dependency: transitive
description:
Expand Down Expand Up @@ -873,6 +888,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.4"
xml:
dependency: transitive
description:
name: xml
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
url: "https://pub.dev"
source: hosted
version: "6.5.0"
yaml:
dependency: transitive
description:
Expand Down
2 changes: 2 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ dependencies:
flutter:
sdk: flutter
flutter_riverpod: ^2.3.6
rss_dart:
path: ../rss.dart/
shared_preferences: ^2.1.2
url_launcher: ^6.1.11
yaml_edit: ^2.2.0
Expand Down

0 comments on commit 918387a

Please sign in to comment.