Skip to content

Commit

Permalink
feat(PreviewCard): Funkwhale support (#252)
Browse files Browse the repository at this point in the history
  • Loading branch information
GeopJr committed May 16, 2023
1 parent 7d90f1a commit 3d602c7
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 31 deletions.
3 changes: 3 additions & 0 deletions src/API/Entity.vala
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ public class Tuba.Entity : GLib.Object, Widgetizable, Json.Serializable {
case "files":
contains = typeof (API.PeerTubeFile);
break;
case "uploads":
contains = typeof (API.FunkwhaleTrack);
break;
default:
contains = typeof (Entity);
break;
Expand Down
7 changes: 7 additions & 0 deletions src/API/Funkwhale.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
public class Tuba.API.Funkwhale : Entity {
public Gee.ArrayList<API.FunkwhaleTrack>? uploads { get; set; default=null; }

public static Funkwhale from (Json.Node node) throws Error {
return Entity.from_json (typeof (API.Funkwhale), node) as API.Funkwhale;
}
}
3 changes: 3 additions & 0 deletions src/API/Funkwhale/Track.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
public class Tuba.API.FunkwhaleTrack : Entity {
public string listen_url { get; set; default=""; }
}
3 changes: 3 additions & 0 deletions src/API/Funkwhale/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
sources += files(
'Track.vala'
)
43 changes: 42 additions & 1 deletion src/API/Status/PreviewCard.vala
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
public class Tuba.API.PreviewCard : Entity {
public enum CardSpecialType {
BASIC,
PEERTUBE,
FUNKWHALE;

public string to_string () {
switch (this) {
case PEERTUBE:
return "PeerTube";
case FUNKWHALE:
return "Funkwhale";
default:
return "";
}
}
}

public string url { get; set; }
public string title { get; set; default=""; }
public string description { get; set; default=""; }
Expand All @@ -8,8 +25,32 @@ public class Tuba.API.PreviewCard : Entity {
public string provider_name { get; set; default=""; }
public string provider_url { get; set; default=""; }
public string? image { get; set; default=null; }
public CardSpecialType card_special_type {
get {
if (is_peertube) {
return CardSpecialType.PEERTUBE;
} else if (is_funkwhale) {
return CardSpecialType.FUNKWHALE;
}

return CardSpecialType.BASIC;
}
}

public bool is_peertube {
get { return kind == "video" && provider_name == "PeerTube"; }
get {
bool url_pt = url.last_index_of ("/videos/watch/") > -1;

return kind == "video" && provider_name == "PeerTube" && url_pt;
}
}

public bool is_funkwhale {
get {
bool provider_fw = provider_name.last_index_of ("- Funkwhale") > 0;
bool url_fw = url.last_index_of ("/library/tracks/") > -1;

return kind == "video" && provider_fw && url_fw;
}
}
}
2 changes: 2 additions & 0 deletions src/API/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ sources += files(
'Emoji.vala',
'EmojiReaction.vala',
'Entity.vala',
'Funkwhale.vala',
'Instance.vala',
'List.vala',
'Mention.vala',
Expand All @@ -22,6 +23,7 @@ sources += files(
)

subdir('Account')
subdir('Funkwhale')
subdir('Instance')
subdir('PeerTube')
subdir('Status')
4 changes: 2 additions & 2 deletions src/Dialogs/MainWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,13 @@ public class Tuba.Dialogs.MainWindow: Adw.ApplicationWindow, Saveable {
media_viewer.set_single_paintable (url, paintable);
}

public void show_media_viewer_peertube(string url, Paintable? preview) {
public void show_media_viewer_remote_video(string url, Paintable? preview, string? user_friendly_url = null) {
if (!is_media_viewer_visible()) {
main_stack.visible_child_name = "media_viewer";
media_viewer.clear.connect(hide_media_viewer);
}

media_viewer.set_peertube (url, preview);
media_viewer.set_remote_video (url, preview, user_friendly_url);
}

public void hide_media_viewer() {
Expand Down
4 changes: 2 additions & 2 deletions src/Views/MediaViewer.vala
Original file line number Diff line number Diff line change
Expand Up @@ -455,9 +455,9 @@ public class Tuba.Views.MediaViewer : Gtk.Box {
});
}

public void set_peertube (string url, Gdk.Paintable? preview) {
public void set_remote_video (string url, Gdk.Paintable? preview, string? user_friendly_url = null) {
var video = new Gtk.Video ();
var item = new Item (video, url, preview, null, true);
var item = new Item (video, user_friendly_url, preview, null, true);

File file = File.new_for_uri (url);
video.set_file(file);
Expand Down
99 changes: 73 additions & 26 deletions src/Widgets/Status.vala
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ public class Tuba.Widgets.Status : ListBoxRow {
// Anything higher is usually very laggy
const int64[] IDEAL_PEERTUBE_RESOLUTION = { 720, 480, 360 };
void open_card_url () {
var peertube = status.formal.card.is_peertube;
var card_special_type = status.formal.card.card_special_type;

var dlg_url = status.formal.card.url;
if (dlg_url.length > 64) {
Expand All @@ -651,8 +651,20 @@ public class Tuba.Widgets.Status : ListBoxRow {

// translators: the variable is a url
var dlg_body = _("If you proceed, \"%s\" will open in your browser.".printf (dlg_url));
if (peertube) {
dlg_title = _("You are about to open a PeerTube video");
if (card_special_type != API.PreviewCard.CardSpecialType.BASIC) {
switch (card_special_type) {
case API.PreviewCard.CardSpecialType.PEERTUBE:
// translators: the variable is an external service like "PeerTube"
dlg_title = _(@"You are about to open a $(card_special_type) video");
break;
case API.PreviewCard.CardSpecialType.FUNKWHALE:
// translators: the variable is an external service like "Funkwhale",
// track as in song
dlg_title = _(@"You are about to open a $(card_special_type) track");
break;
default:
assert_not_reached ();
}

// translators: the first variable is the app name (Tuba),
// the second one is a url
Expand All @@ -669,39 +681,74 @@ public class Tuba.Widgets.Status : ListBoxRow {

privacy_dialog.response.connect(res => {
if (res == "yes") {
if (peertube) {
if (card_special_type != API.PreviewCard.CardSpecialType.BASIC) {
try {
var peertube_instance = GLib.Uri.parse (status.formal.card.url, GLib.UriFlags.NONE);
var peertube_api_video = @"https://$(peertube_instance.get_host ())/api/v1/videos/$(Path.get_basename (peertube_instance.get_path ()))";
new Request.GET (peertube_api_video)
var special_api_url = "";
var special_host = "";
switch (card_special_type) {
case API.PreviewCard.CardSpecialType.PEERTUBE:
var peertube_instance = GLib.Uri.parse (status.formal.card.url, GLib.UriFlags.NONE);
special_host = peertube_instance.get_host ();
special_api_url = @"https://$(special_host)/api/v1/videos/$(Path.get_basename (peertube_instance.get_path ()))";
break;
case API.PreviewCard.CardSpecialType.FUNKWHALE:
var funkwhale_instance = GLib.Uri.parse (status.formal.card.url, GLib.UriFlags.NONE);
special_host = funkwhale_instance.get_host ();
special_api_url = @"https://$(special_host)/api/v1/tracks/$(Path.get_basename (funkwhale_instance.get_path ()))";
break;
default:
assert_not_reached ();
}

new Request.GET (special_api_url)
.then ((sess, msg, in_stream) => {
var failed = true;
var parser = Network.get_parser_from_inputstream(in_stream);
var node = network.parse_node (parser);
var peertube_obj = API.PeerTube.from (node);

if (peertube_obj.url == status.formal.card.url) {
if (peertube_obj.streamingPlaylists != null && peertube_obj.streamingPlaylists.size > 0) {
var peertube_streaming_playlist = peertube_obj.streamingPlaylists.get(0);
if (peertube_streaming_playlist.files != null && peertube_streaming_playlist.files.size > 0) {
var res_url = "";
peertube_streaming_playlist.files.foreach (file => {
if (file.fileDownloadUrl == "" || file.resolution == null) return true;
res_url = file.fileDownloadUrl;

if (file.resolution.id in IDEAL_PEERTUBE_RESOLUTION) return false;
return true;
});

if (res_url != "") {
var res_url = "";

switch (card_special_type) {
case API.PreviewCard.CardSpecialType.PEERTUBE:
var peertube_obj = API.PeerTube.from (node);

if (peertube_obj.url == status.formal.card.url) {
if (peertube_obj.streamingPlaylists != null && peertube_obj.streamingPlaylists.size > 0) {
var peertube_streaming_playlist = peertube_obj.streamingPlaylists.get(0);
if (peertube_streaming_playlist.files != null && peertube_streaming_playlist.files.size > 0) {
peertube_streaming_playlist.files.foreach (file => {
if (file.fileDownloadUrl == "" || file.resolution == null) return true;
res_url = file.fileDownloadUrl;

if (file.resolution.id in IDEAL_PEERTUBE_RESOLUTION) return false;
return true;
});

if (res_url != "") failed = false;
}
}
}
break;
case API.PreviewCard.CardSpecialType.FUNKWHALE:
var funkwhale_obj = API.Funkwhale.from (node);

if (funkwhale_obj.uploads != null && funkwhale_obj.uploads.size > 0) {
var funkwhale_track = funkwhale_obj.uploads.get(0);

if (funkwhale_track.listen_url != "") {
failed = false;
app.main_window.show_media_viewer_peertube (res_url, null);
res_url = @"https://$(special_host)$(funkwhale_track.listen_url)";
}
}
}
break;
default:
assert_not_reached ();
}

if (failed) Host.open_uri (status.formal.card.url);
if (failed || res_url == "") {
Host.open_uri (status.formal.card.url);
} else {
app.main_window.show_media_viewer_remote_video (res_url, null, status.formal.card.url);
}
})
.on_error (() => {
Host.open_uri (status.formal.card.url);
Expand Down

0 comments on commit 3d602c7

Please sign in to comment.