Skip to content

Commit

Permalink
feat: re-introduce youtube API along with piped
Browse files Browse the repository at this point in the history
  • Loading branch information
KRTirtho committed Jun 30, 2023
1 parent b47ef98 commit b54ee96
Show file tree
Hide file tree
Showing 20 changed files with 537 additions and 251 deletions.
66 changes: 28 additions & 38 deletions lib/components/player/sibling_tracks_sheet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@ import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:piped_client/piped_client.dart';
import 'package:spotify/spotify.dart' hide Offset;
import 'package:spotube/collections/spotube_icons.dart';

import 'package:spotube/components/shared/image/universal_image.dart';
import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/hooks/use_debounce.dart';
import 'package:spotube/models/matched_track.dart';
import 'package:spotube/models/spotube_track.dart';
import 'package:spotube/provider/piped_provider.dart';
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
import 'package:spotube/provider/user_preferences_provider.dart';
import 'package:spotube/provider/youtube_provider.dart';
import 'package:spotube/services/youtube/youtube.dart';
import 'package:spotube/utils/primitive_utils.dart';
import 'package:spotube/utils/service_utils.dart';
import 'package:spotube/utils/type_conversion_utils.dart';
Expand All @@ -31,12 +32,11 @@ class SiblingTracksSheet extends HookConsumerWidget {
final theme = Theme.of(context);
final playlist = ref.watch(ProxyPlaylistNotifier.provider);
final playlistNotifier = ref.watch(ProxyPlaylistNotifier.notifier);
final preferencesSearchMode =
ref.watch(userPreferencesProvider.select((value) => value.searchMode));
final pipedClient = ref.watch(pipedClientProvider);
final preferences = ref.watch(userPreferencesProvider);
final youtube = ref.watch(youtubeProvider);

final isSearching = useState(false);
final searchMode = useState(preferencesSearchMode);
final searchMode = useState(preferences.searchMode);

final title = ServiceUtils.getTitle(
playlist.activeTrack?.name ?? "",
Expand All @@ -57,29 +57,18 @@ class SiblingTracksSheet extends HookConsumerWidget {

final searchRequest = useMemoized(() async {
if (searchTerm.trim().isEmpty) {
return <PipedSearchItemStream>[];
return <YoutubeVideoInfo>[];
}

return pipedClient
.search(
searchTerm.trim(),
switch (searchMode.value) {
SearchMode.youtube => PipedFilter.video,
SearchMode.youtubeMusic => PipedFilter.musicSongs,
},
)
.then(
(result) =>
result.items.whereType<PipedSearchItemStream>().toList(),
);
return youtube.search(searchTerm.trim());
}, [
searchTerm,
searchMode.value,
]);

final siblings = playlist.isFetching == false
? (playlist.activeTrack as SpotubeTrack).siblings
: <PipedSearchItemStream>[];
: <YoutubeVideoInfo>[];

final borderRadius = floating
? BorderRadius.circular(10)
Expand All @@ -96,13 +85,13 @@ class SiblingTracksSheet extends HookConsumerWidget {
return null;
}, [playlist.activeTrack]);

final itemBuilder = useCallback((PipedSearchItemStream video) {
final itemBuilder = useCallback((YoutubeVideoInfo video) {
return ListTile(
title: Text(video.title),
leading: Padding(
padding: const EdgeInsets.all(8.0),
child: UniversalImage(
path: video.thumbnail,
path: video.thumbnailUrl,
height: 60,
width: 60,
),
Expand All @@ -113,7 +102,7 @@ class SiblingTracksSheet extends HookConsumerWidget {
trailing: Text(
PrimitiveUtils.toReadableDuration(video.duration),
),
subtitle: Text(video.uploaderName),
subtitle: Text(video.channelName),
enabled: playlist.isFetching != true,
selected: playlist.isFetching != true &&
video.id == (playlist.activeTrack as SpotubeTrack).ytTrack.id,
Expand Down Expand Up @@ -182,21 +171,22 @@ class SiblingTracksSheet extends HookConsumerWidget {
},
)
else ...[
PopupMenuButton(
icon: const Icon(SpotubeIcons.filter, size: 18),
onSelected: (SearchMode mode) {
searchMode.value = mode;
},
initialValue: searchMode.value,
itemBuilder: (context) => SearchMode.values
.map(
(e) => PopupMenuItem(
value: e,
child: Text(e.label),
),
)
.toList(),
),
if (preferences.youtubeApiType == YoutubeApiType.piped)
PopupMenuButton(
icon: const Icon(SpotubeIcons.filter, size: 18),
onSelected: (SearchMode mode) {
searchMode.value = mode;
},
initialValue: searchMode.value,
itemBuilder: (context) => SearchMode.values
.map(
(e) => PopupMenuItem(
value: e,
child: Text(e.label),
),
)
.toList(),
),
IconButton(
icon: const Icon(SpotubeIcons.close, size: 18),
onPressed: () {
Expand Down
4 changes: 2 additions & 2 deletions lib/components/shared/dialogs/track_details_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ class TrackDetailsDialog extends HookWidget {
overflow: TextOverflow.ellipsis,
),
context.l10n.channel: Hyperlink(
ytTrack.uploader,
"https://youtube.com${ytTrack.uploaderUrl}",
ytTrack.channelName,
"https://youtube.com${ytTrack.channelName}",
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
Expand Down
3 changes: 2 additions & 1 deletion lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -248,5 +248,6 @@
"logs": "Logs",
"developers": "Developers",
"not_logged_in": "You're not logged in",
"search_mode": "Search Mode"
"search_mode": "Search Mode",
"youtube_api_type": "YouTube API Type"
}
1 change: 1 addition & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ Future<void> main(List<String> rawArgs) async {
);
Hive.registerAdapter(MatchedTrackAdapter());
Hive.registerAdapter(SkipSegmentAdapter());
Hive.registerAdapter(SearchModeAdapter());

await Hive.openLazyBox<MatchedTrack>(
MatchedTrack.boxName,
Expand Down
25 changes: 24 additions & 1 deletion lib/models/matched_track.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import "package:hive/hive.dart";

part "matched_track.g.dart";

@HiveType(typeId: 1)
Expand All @@ -8,6 +7,8 @@ class MatchedTrack {
String youtubeId;
@HiveField(1)
String spotifyId;
@HiveField(2)
SearchMode searchMode;

String? id;
DateTime? createdAt;
Expand All @@ -21,12 +22,14 @@ class MatchedTrack {
MatchedTrack({
required this.youtubeId,
required this.spotifyId,
required this.searchMode,
this.id,
this.createdAt,
});

factory MatchedTrack.fromJson(Map<String, dynamic> json) {
return MatchedTrack(
searchMode: SearchMode.fromString(json["searchMode"]),
youtubeId: json["youtube_id"],
spotifyId: json["spotify_id"],
id: json["id"],
Expand All @@ -39,7 +42,27 @@ class MatchedTrack {
"youtube_id": youtubeId,
"spotify_id": spotifyId,
"id": id,
"searchMode": searchMode.name,
"created_at": createdAt?.toString()
}..removeWhere((key, value) => value == null);
}
}

@HiveType(typeId: 4)
enum SearchMode {
@HiveField(0)
youtube._internal('YouTube'),
@HiveField(1)
youtubeMusic._internal('YouTube Music');

final String label;

const SearchMode._internal(this.label);

factory SearchMode.fromString(String value) {
return SearchMode.values.firstWhere(
(element) => element.name == value,
orElse: () => SearchMode.youtube,
);
}
}
46 changes: 44 additions & 2 deletions lib/models/matched_track.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit b54ee96

Please sign in to comment.