mirror of
https://github.com/LemmyNet/joinlemmy-site.git
synced 2024-11-22 04:11:15 +00:00
Adding Apps page filtering by platform. Fixes #256
This commit is contained in:
parent
17ecc71ba8
commit
9f51895a6b
8 changed files with 388 additions and 313 deletions
|
@ -1 +1 @@
|
||||||
Subproject commit 63e8c68ffc724a7e4e44de17c236c44d9b66d028
|
Subproject commit 35366c5ec0f198860bb860e4c7b5deda9e47636a
|
|
@ -1 +1 @@
|
||||||
Subproject commit ff8a2db505771c9f142ab31626b49de54a756192
|
Subproject commit 419d6e7c67951d1210226091b2d09a0536b531c8
|
|
@ -9,6 +9,14 @@ export enum SourceType {
|
||||||
Open,
|
Open,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum Platform {
|
||||||
|
All = "all_platforms",
|
||||||
|
Android = "android",
|
||||||
|
IOS = "ios",
|
||||||
|
Web = "web",
|
||||||
|
CLI = "cli",
|
||||||
|
}
|
||||||
|
|
||||||
export interface AppDetails {
|
export interface AppDetails {
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
@ -17,6 +25,7 @@ export interface AppDetails {
|
||||||
banner?: string;
|
banner?: string;
|
||||||
links: AppLink[];
|
links: AppLink[];
|
||||||
sourceType: SourceType;
|
sourceType: SourceType;
|
||||||
|
platforms: Platform[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AppLink {
|
export interface AppLink {
|
||||||
|
@ -43,7 +52,7 @@ export const API_LIBRARIES: ApiLibrary[] = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const voyagerApp: AppDetails = {
|
const VOYAGER: AppDetails = {
|
||||||
name: "Voyager",
|
name: "Voyager",
|
||||||
description: "A Lemmy Client for iOS, Android and the web",
|
description: "A Lemmy Client for iOS, Android and the web",
|
||||||
link: "https://github.com/aeharding/voyager",
|
link: "https://github.com/aeharding/voyager",
|
||||||
|
@ -64,9 +73,10 @@ const voyagerApp: AppDetails = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
sourceType: SourceType.Open,
|
sourceType: SourceType.Open,
|
||||||
|
platforms: [Platform.Android, Platform.IOS, Platform.Web],
|
||||||
};
|
};
|
||||||
|
|
||||||
const thunderApp: AppDetails = {
|
const THUNDER: AppDetails = {
|
||||||
name: "Thunder",
|
name: "Thunder",
|
||||||
description:
|
description:
|
||||||
"An open-source cross-platform Lemmy client for iOS and Android built with Flutter",
|
"An open-source cross-platform Lemmy client for iOS and Android built with Flutter",
|
||||||
|
@ -92,268 +102,303 @@ const thunderApp: AppDetails = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
sourceType: SourceType.Open,
|
sourceType: SourceType.Open,
|
||||||
|
platforms: [Platform.Android, Platform.IOS],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ANDROID_APPS: AppDetails[] = [
|
const JERBOA: AppDetails = {
|
||||||
{
|
name: "Jerboa",
|
||||||
name: "Jerboa",
|
description: "A native Android app made by Lemmy's developers",
|
||||||
description: "A native Android app made by Lemmy's developers",
|
link: "https://github.com/dessalines/jerboa",
|
||||||
link: "https://github.com/dessalines/jerboa",
|
icon: "/static/assets/images/jerboa.svg",
|
||||||
icon: "/static/assets/images/jerboa.svg",
|
banner: "/static/assets/images/jerboa_screen.webp",
|
||||||
banner: "/static/assets/images/jerboa_screen.webp",
|
links: [
|
||||||
links: [
|
{
|
||||||
{
|
link: "https://f-droid.org/en/packages/com.jerboa",
|
||||||
link: "https://f-droid.org/en/packages/com.jerboa",
|
icon: "f-droid",
|
||||||
icon: "f-droid",
|
},
|
||||||
},
|
{
|
||||||
{
|
link: "https://play.google.com/store/apps/details?id=com.jerboa",
|
||||||
link: "https://play.google.com/store/apps/details?id=com.jerboa",
|
icon: "googleplay",
|
||||||
icon: "googleplay",
|
},
|
||||||
},
|
{
|
||||||
{
|
link: "https://github.com/dessalines/jerboa",
|
||||||
link: "https://github.com/dessalines/jerboa",
|
icon: "github",
|
||||||
icon: "github",
|
},
|
||||||
},
|
],
|
||||||
],
|
sourceType: SourceType.Open,
|
||||||
sourceType: SourceType.Open,
|
platforms: [Platform.Android],
|
||||||
},
|
};
|
||||||
{
|
|
||||||
name: "Eternity",
|
|
||||||
description: "A Lemmy client for Android written in Java.",
|
|
||||||
link: "https://codeberg.org/Bazsalanszky/Eternity",
|
|
||||||
icon: "/static/assets/images/eternity_icon.webp",
|
|
||||||
banner: "/static/assets/images/eternity_screen.webp",
|
|
||||||
links: [
|
|
||||||
{
|
|
||||||
link: "https://apt.izzysoft.de/fdroid/index/apk/eu.toldi.infinityforlemmy",
|
|
||||||
icon: "f-droid",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
link: "https://play.google.com/store/apps/details?id=eu.toldi.infinityforlemmy",
|
|
||||||
icon: "googleplay",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
link: "https://codeberg.org/Bazsalanszky/Eternity",
|
|
||||||
icon: "github",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
sourceType: SourceType.Open,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Combustible",
|
|
||||||
description: "An Open-Source Lemmy Client For Android",
|
|
||||||
link: "https://github.com/TheBrokenRail/Combustible",
|
|
||||||
icon: "/static/assets/images/combustible_logo.webp",
|
|
||||||
banner: "/static/assets/images/combustible_screen.webp",
|
|
||||||
links: [
|
|
||||||
{
|
|
||||||
link: "https://apt.izzysoft.de/fdroid/index/apk/com.thebrokenrail.combustible",
|
|
||||||
icon: "f-droid",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
link: "https://github.com/TheBrokenRail/Combustible",
|
|
||||||
icon: "github",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
sourceType: SourceType.Open,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "LiftOff!",
|
|
||||||
description: "A mobile client for lemmy",
|
|
||||||
link: "https://github.com/liftoff-app/liftoff",
|
|
||||||
icon: "/static/assets/images/liftoff_icon.svg",
|
|
||||||
banner: "/static/assets/images/liftoff_screen.webp",
|
|
||||||
links: [
|
|
||||||
{
|
|
||||||
link: "https://apt.izzysoft.de/fdroid/index/apk/com.liftoffapp.liftoff",
|
|
||||||
icon: "f-droid",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
link: "https://play.google.com/store/apps/details?id=com.liftoffapp.liftoff&pli=1",
|
|
||||||
icon: "googleplay",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
link: "https://github.com/liftoff-app/liftoff",
|
|
||||||
icon: "github",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
sourceType: SourceType.Open,
|
|
||||||
},
|
|
||||||
voyagerApp,
|
|
||||||
thunderApp,
|
|
||||||
{
|
|
||||||
name: "Boost for Lemmy",
|
|
||||||
description: "A smooth app for Lemmy.",
|
|
||||||
link: "https://play.google.com/store/apps/details?id=com.rubenmayayo.lemmy",
|
|
||||||
icon: "/static/assets/images/boost_icon.webp",
|
|
||||||
banner: "/static/assets/images/boost_screen.webp",
|
|
||||||
links: [
|
|
||||||
{
|
|
||||||
link: "https://play.google.com/store/apps/details?id=com.rubenmayayo.lemmy",
|
|
||||||
icon: "googleplay",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
sourceType: SourceType.Closed,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Sync for Lemmy",
|
|
||||||
description: "A full-featured app for browsing Lemmy on the go.",
|
|
||||||
link: "https://play.google.com/store/apps/details?id=io.syncapps.lemmy_sync",
|
|
||||||
icon: "/static/assets/images/sync_icon.webp",
|
|
||||||
banner: "/static/assets/images/sync_screen.webp",
|
|
||||||
links: [
|
|
||||||
{
|
|
||||||
link: "https://play.google.com/store/apps/details?id=io.syncapps.lemmy_sync",
|
|
||||||
icon: "googleplay",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
sourceType: SourceType.Closed,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const IOS_APPS: AppDetails[] = [
|
const ETERNITY: AppDetails = {
|
||||||
{
|
name: "Eternity",
|
||||||
name: "Mlem",
|
description: "A Lemmy client for Android written in Java.",
|
||||||
description: "A Lemmy Client for iOS.",
|
link: "https://codeberg.org/Bazsalanszky/Eternity",
|
||||||
link: "https://github.com/mormaer/Mlem",
|
icon: "/static/assets/images/eternity_icon.webp",
|
||||||
icon: "/static/assets/images/mlem.png",
|
banner: "/static/assets/images/eternity_screen.webp",
|
||||||
banner: "/static/assets/images/mlem_screen.webp",
|
links: [
|
||||||
links: [
|
{
|
||||||
{
|
link: "https://apt.izzysoft.de/fdroid/index/apk/eu.toldi.infinityforlemmy",
|
||||||
link: "https://testflight.apple.com/join/MelFP11Y",
|
icon: "f-droid",
|
||||||
icon: "appleinc",
|
},
|
||||||
},
|
{
|
||||||
{
|
link: "https://play.google.com/store/apps/details?id=eu.toldi.infinityforlemmy",
|
||||||
link: "https://github.com/mlemgroup/mlem",
|
icon: "googleplay",
|
||||||
icon: "github",
|
},
|
||||||
},
|
{
|
||||||
],
|
link: "https://codeberg.org/Bazsalanszky/Eternity",
|
||||||
sourceType: SourceType.Open,
|
icon: "github",
|
||||||
},
|
},
|
||||||
{
|
],
|
||||||
name: "Lunar",
|
sourceType: SourceType.Open,
|
||||||
description: "A Lemmy Client for iOS written in Swift and SwiftUI",
|
platforms: [Platform.Android],
|
||||||
link: "https://github.com/mani-sh-reddy/Lunar",
|
};
|
||||||
icon: "/static/assets/images/lunar_logo.webp",
|
|
||||||
banner: "/static/assets/images/lunar_screen.webp",
|
|
||||||
links: [
|
|
||||||
{
|
|
||||||
link: "https://testflight.apple.com/join/GEFCCQTb",
|
|
||||||
icon: "appleinc",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
link: "https://github.com/mani-sh-reddy/Lunar",
|
|
||||||
icon: "github",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
sourceType: SourceType.Open,
|
|
||||||
},
|
|
||||||
voyagerApp,
|
|
||||||
thunderApp,
|
|
||||||
{
|
|
||||||
name: "Memmy",
|
|
||||||
description:
|
|
||||||
"A Lemmy Client built in React Native for iOS available on the App Store.",
|
|
||||||
link: "https://github.com/Memmy-App/memmy",
|
|
||||||
icon: "/static/assets/images/memmy_icon.png",
|
|
||||||
banner: "/static/assets/images/memmy_banner.webp",
|
|
||||||
links: [
|
|
||||||
{
|
|
||||||
link: "https://apps.apple.com/us/app/memmy-for-lemmy/id6450204299?platform=iphone",
|
|
||||||
icon: "appleinc",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
link: "https://github.com/Memmy-App/memmy",
|
|
||||||
icon: "github",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
sourceType: SourceType.Open,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const WEB_APPS: AppDetails[] = [
|
const COMBUSTIBLE: AppDetails = {
|
||||||
{
|
name: "Combustible",
|
||||||
name: "lemmy-ui",
|
description: "An Open-Source Lemmy Client For Android",
|
||||||
description: "The official web app for lemmy.",
|
link: "https://github.com/TheBrokenRail/Combustible",
|
||||||
link: "https://github.com/LemmyNet/lemmy-ui",
|
icon: "/static/assets/images/combustible_logo.webp",
|
||||||
banner: "/static/assets/images/mobile_pic.webp",
|
banner: "/static/assets/images/combustible_screen.webp",
|
||||||
links: [
|
links: [
|
||||||
{
|
{
|
||||||
link: "https://github.com/LemmyNet/lemmy-ui",
|
link: "https://apt.izzysoft.de/fdroid/index/apk/com.thebrokenrail.combustible",
|
||||||
icon: "github",
|
icon: "f-droid",
|
||||||
},
|
},
|
||||||
],
|
{
|
||||||
sourceType: SourceType.Open,
|
link: "https://github.com/TheBrokenRail/Combustible",
|
||||||
},
|
icon: "github",
|
||||||
{
|
},
|
||||||
name: "Photon",
|
],
|
||||||
description: "A sleek lemmy web UI.",
|
sourceType: SourceType.Open,
|
||||||
link: "https://github.com/Xyphyn/photon",
|
platforms: [Platform.Android],
|
||||||
banner: "/static/assets/images/photon.webp",
|
};
|
||||||
icon: "/static/assets/images/photon-logo.svg",
|
|
||||||
links: [
|
|
||||||
{
|
|
||||||
link: "https://github.com/Xyphyn/photon",
|
|
||||||
icon: "github",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
sourceType: SourceType.Open,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Alexandrite",
|
|
||||||
description:
|
|
||||||
"A beautiful and convenient desktop-first alternate web UI for Lemmy.",
|
|
||||||
link: "https://github.com/sheodox/alexandrite",
|
|
||||||
icon: "/static/assets/images/alexandrite_logo.svg",
|
|
||||||
banner: "/static/assets/images/alexandrite_screen.webp",
|
|
||||||
links: [
|
|
||||||
{
|
|
||||||
link: "https://github.com/sheodox/alexandrite",
|
|
||||||
icon: "github",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
sourceType: SourceType.Open,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "mlmym",
|
|
||||||
description: "A familiar desktop experience for lemmy",
|
|
||||||
link: "https://github.com/rystaf/mlmym",
|
|
||||||
banner: "/static/assets/images/mlmym_screen.webp",
|
|
||||||
links: [
|
|
||||||
{
|
|
||||||
link: "https://github.com/rystaf/mlmym",
|
|
||||||
icon: "github",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
sourceType: SourceType.Open,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "lemmyBB",
|
|
||||||
description: "A lemmy frontend based on phpBB.",
|
|
||||||
link: "https://github.com/LemmyNet/lemmyBB",
|
|
||||||
banner: "/static/assets/images/lemmybb_2.webp",
|
|
||||||
links: [
|
|
||||||
{
|
|
||||||
link: "https://github.com/LemmyNet/lemmyBB",
|
|
||||||
icon: "github",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
sourceType: SourceType.Open,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const CLI_APPS: AppDetails[] = [
|
const LIFTOFF: AppDetails = {
|
||||||
{
|
name: "LiftOff!",
|
||||||
name: "neonmodem",
|
description: "A mobile client for lemmy",
|
||||||
description: "BBS-style TUI client",
|
link: "https://github.com/liftoff-app/liftoff",
|
||||||
link: "https://github.com/mrusme/neonmodem",
|
icon: "/static/assets/images/liftoff_icon.svg",
|
||||||
banner: "/static/assets/images/neonmodem.webp",
|
banner: "/static/assets/images/liftoff_screen.webp",
|
||||||
links: [
|
links: [
|
||||||
{
|
{
|
||||||
link: "https://github.com/mrusme/neonmodem",
|
link: "https://apt.izzysoft.de/fdroid/index/apk/com.liftoffapp.liftoff",
|
||||||
icon: "github",
|
icon: "f-droid",
|
||||||
},
|
},
|
||||||
],
|
{
|
||||||
sourceType: SourceType.Open,
|
link: "https://play.google.com/store/apps/details?id=com.liftoffapp.liftoff&pli=1",
|
||||||
},
|
icon: "googleplay",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
link: "https://github.com/liftoff-app/liftoff",
|
||||||
|
icon: "github",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
sourceType: SourceType.Open,
|
||||||
|
platforms: [Platform.Android, Platform.IOS],
|
||||||
|
};
|
||||||
|
|
||||||
|
const BOOST: AppDetails = {
|
||||||
|
name: "Boost for Lemmy",
|
||||||
|
description: "A smooth app for Lemmy.",
|
||||||
|
link: "https://play.google.com/store/apps/details?id=com.rubenmayayo.lemmy",
|
||||||
|
icon: "/static/assets/images/boost_icon.webp",
|
||||||
|
banner: "/static/assets/images/boost_screen.webp",
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
link: "https://play.google.com/store/apps/details?id=com.rubenmayayo.lemmy",
|
||||||
|
icon: "googleplay",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
sourceType: SourceType.Closed,
|
||||||
|
platforms: [Platform.Android],
|
||||||
|
};
|
||||||
|
|
||||||
|
const SYNC: AppDetails = {
|
||||||
|
name: "Sync for Lemmy",
|
||||||
|
description: "A full-featured app for browsing Lemmy on the go.",
|
||||||
|
link: "https://play.google.com/store/apps/details?id=io.syncapps.lemmy_sync",
|
||||||
|
icon: "/static/assets/images/sync_icon.webp",
|
||||||
|
banner: "/static/assets/images/sync_screen.webp",
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
link: "https://play.google.com/store/apps/details?id=io.syncapps.lemmy_sync",
|
||||||
|
icon: "googleplay",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
sourceType: SourceType.Closed,
|
||||||
|
platforms: [Platform.Android],
|
||||||
|
};
|
||||||
|
|
||||||
|
const MLEM: AppDetails = {
|
||||||
|
name: "Mlem",
|
||||||
|
description: "A Lemmy Client for iOS.",
|
||||||
|
link: "https://github.com/mormaer/Mlem",
|
||||||
|
icon: "/static/assets/images/mlem.png",
|
||||||
|
banner: "/static/assets/images/mlem_screen.webp",
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
link: "https://testflight.apple.com/join/MelFP11Y",
|
||||||
|
icon: "appleinc",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
link: "https://github.com/mlemgroup/mlem",
|
||||||
|
icon: "github",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
sourceType: SourceType.Open,
|
||||||
|
platforms: [Platform.IOS],
|
||||||
|
};
|
||||||
|
|
||||||
|
const LUNAR: AppDetails = {
|
||||||
|
name: "Lunar",
|
||||||
|
description: "A Lemmy Client for iOS written in Swift and SwiftUI",
|
||||||
|
link: "https://github.com/mani-sh-reddy/Lunar",
|
||||||
|
icon: "/static/assets/images/lunar_logo.webp",
|
||||||
|
banner: "/static/assets/images/lunar_screen.webp",
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
link: "https://testflight.apple.com/join/GEFCCQTb",
|
||||||
|
icon: "appleinc",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
link: "https://github.com/mani-sh-reddy/Lunar",
|
||||||
|
icon: "github",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
sourceType: SourceType.Open,
|
||||||
|
platforms: [Platform.IOS],
|
||||||
|
};
|
||||||
|
|
||||||
|
const MEMMY: AppDetails = {
|
||||||
|
name: "Memmy",
|
||||||
|
description:
|
||||||
|
"A Lemmy Client built in React Native for iOS available on the App Store.",
|
||||||
|
link: "https://github.com/Memmy-App/memmy",
|
||||||
|
icon: "/static/assets/images/memmy_icon.png",
|
||||||
|
banner: "/static/assets/images/memmy_banner.webp",
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
link: "https://apps.apple.com/us/app/memmy-for-lemmy/id6450204299?platform=iphone",
|
||||||
|
icon: "appleinc",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
link: "https://github.com/Memmy-App/memmy",
|
||||||
|
icon: "github",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
sourceType: SourceType.Open,
|
||||||
|
platforms: [Platform.IOS],
|
||||||
|
};
|
||||||
|
|
||||||
|
const LEMMY_UI: AppDetails = {
|
||||||
|
name: "lemmy-ui",
|
||||||
|
description: "The official web app for lemmy.",
|
||||||
|
link: "https://github.com/LemmyNet/lemmy-ui",
|
||||||
|
banner: "/static/assets/images/mobile_pic.webp",
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
link: "https://github.com/LemmyNet/lemmy-ui",
|
||||||
|
icon: "github",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
sourceType: SourceType.Open,
|
||||||
|
platforms: [Platform.Web],
|
||||||
|
};
|
||||||
|
|
||||||
|
const PHOTON: AppDetails = {
|
||||||
|
name: "Photon",
|
||||||
|
description: "A sleek lemmy web UI.",
|
||||||
|
link: "https://github.com/Xyphyn/photon",
|
||||||
|
banner: "/static/assets/images/photon.webp",
|
||||||
|
icon: "/static/assets/images/photon-logo.svg",
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
link: "https://github.com/Xyphyn/photon",
|
||||||
|
icon: "github",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
sourceType: SourceType.Open,
|
||||||
|
platforms: [Platform.Web],
|
||||||
|
};
|
||||||
|
|
||||||
|
const ALEXANDRITE: AppDetails = {
|
||||||
|
name: "Alexandrite",
|
||||||
|
description:
|
||||||
|
"A beautiful and convenient desktop-first alternate web UI for Lemmy.",
|
||||||
|
link: "https://github.com/sheodox/alexandrite",
|
||||||
|
icon: "/static/assets/images/alexandrite_logo.svg",
|
||||||
|
banner: "/static/assets/images/alexandrite_screen.webp",
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
link: "https://github.com/sheodox/alexandrite",
|
||||||
|
icon: "github",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
sourceType: SourceType.Open,
|
||||||
|
platforms: [Platform.Web],
|
||||||
|
};
|
||||||
|
|
||||||
|
const MLMYM: AppDetails = {
|
||||||
|
name: "mlmym",
|
||||||
|
description: "A familiar desktop experience for lemmy",
|
||||||
|
link: "https://github.com/rystaf/mlmym",
|
||||||
|
banner: "/static/assets/images/mlmym_screen.webp",
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
link: "https://github.com/rystaf/mlmym",
|
||||||
|
icon: "github",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
sourceType: SourceType.Open,
|
||||||
|
platforms: [Platform.Web],
|
||||||
|
};
|
||||||
|
|
||||||
|
const LEMMYBB: AppDetails = {
|
||||||
|
name: "lemmyBB",
|
||||||
|
description: "A lemmy frontend based on phpBB.",
|
||||||
|
link: "https://github.com/LemmyNet/lemmyBB",
|
||||||
|
banner: "/static/assets/images/lemmybb_2.webp",
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
link: "https://github.com/LemmyNet/lemmyBB",
|
||||||
|
icon: "github",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
sourceType: SourceType.Open,
|
||||||
|
platforms: [Platform.Web],
|
||||||
|
};
|
||||||
|
|
||||||
|
const NEONMODEM: AppDetails = {
|
||||||
|
name: "neonmodem",
|
||||||
|
description: "BBS-style TUI client",
|
||||||
|
link: "https://github.com/mrusme/neonmodem",
|
||||||
|
banner: "/static/assets/images/neonmodem.webp",
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
link: "https://github.com/mrusme/neonmodem",
|
||||||
|
icon: "github",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
sourceType: SourceType.Open,
|
||||||
|
platforms: [Platform.CLI],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const APP_LIST: AppDetails[] = [
|
||||||
|
JERBOA,
|
||||||
|
ETERNITY,
|
||||||
|
COMBUSTIBLE,
|
||||||
|
LIFTOFF,
|
||||||
|
MLEM,
|
||||||
|
LUNAR,
|
||||||
|
MEMMY,
|
||||||
|
LEMMY_UI,
|
||||||
|
VOYAGER,
|
||||||
|
THUNDER,
|
||||||
|
PHOTON,
|
||||||
|
ALEXANDRITE,
|
||||||
|
MLMYM,
|
||||||
|
LEMMYBB,
|
||||||
|
NEONMODEM,
|
||||||
|
BOOST,
|
||||||
|
SYNC,
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,22 +1,21 @@
|
||||||
import { Component } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { Helmet } from "inferno-helmet";
|
import { Helmet } from "inferno-helmet";
|
||||||
import { i18n } from "../i18next";
|
import { i18n } from "../i18next";
|
||||||
import { T } from "inferno-i18next";
|
import { T } from "inferno-i18next";
|
||||||
import { BottomSpacer, TEXT_GRADIENT } from "./common";
|
import { BottomSpacer, SELECT_CLASSES, TEXT_GRADIENT } from "./common";
|
||||||
import {
|
import {
|
||||||
ANDROID_APPS,
|
|
||||||
API_LIBRARIES,
|
API_LIBRARIES,
|
||||||
|
APP_LIST,
|
||||||
AppDetails,
|
AppDetails,
|
||||||
AppLink,
|
AppLink,
|
||||||
CLI_APPS,
|
Platform,
|
||||||
IOS_APPS,
|
|
||||||
SourceType,
|
SourceType,
|
||||||
WEB_APPS,
|
|
||||||
} from "./app-definitions";
|
} from "./app-definitions";
|
||||||
import { Icon } from "./icon";
|
import { Icon } from "./icon";
|
||||||
|
import { I18nKeys } from "i18next";
|
||||||
|
|
||||||
const TitleBlock = () => (
|
const TitleBlock = () => (
|
||||||
<div className="flex flex-col items-center pt-16 mb-8">
|
<div className="flex flex-col items-center pt-16 mb-4">
|
||||||
<T i18nKey="lemmy_apps" className="text-4xl font-bold mb-3">
|
<T i18nKey="lemmy_apps" className="text-4xl font-bold mb-3">
|
||||||
#<span className={TEXT_GRADIENT}>#</span>
|
#<span className={TEXT_GRADIENT}>#</span>
|
||||||
</T>
|
</T>
|
||||||
|
@ -83,29 +82,6 @@ const AppTitle = ({ title }) => (
|
||||||
<div className="text-2xl mb-3 text-gray-300">{title}</div>
|
<div className="text-2xl mb-3 text-gray-300">{title}</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const MobileAppsBlock = () => (
|
|
||||||
<div>
|
|
||||||
<AppTitle title={i18n.t("mobile_apps_for_android")} />
|
|
||||||
<AppGrid apps={ANDROID_APPS} />
|
|
||||||
<AppTitle title={i18n.t("mobile_apps_for_ios")} />
|
|
||||||
<AppGrid apps={IOS_APPS} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const WebAppsBlock = () => (
|
|
||||||
<div>
|
|
||||||
<AppTitle title={i18n.t("web_apps")} />
|
|
||||||
<AppGrid apps={WEB_APPS} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const CliAppsBlock = () => (
|
|
||||||
<div>
|
|
||||||
<AppTitle title={i18n.t("cli_apps")} />
|
|
||||||
<AppGrid apps={CLI_APPS} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
interface AppGridProps {
|
interface AppGridProps {
|
||||||
apps: AppDetails[];
|
apps: AppDetails[];
|
||||||
}
|
}
|
||||||
|
@ -142,13 +118,35 @@ const ApiLibrariesBlock = () => (
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
export class Apps extends Component<any, any> {
|
interface State {
|
||||||
|
apps: AppDetails[];
|
||||||
|
platform: Platform;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Apps extends Component<any, State> {
|
||||||
|
state: State = {
|
||||||
|
apps: [],
|
||||||
|
platform: Platform.All,
|
||||||
|
};
|
||||||
|
|
||||||
constructor(props: any, context: any) {
|
constructor(props: any, context: any) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
|
this.buildAppList();
|
||||||
|
}
|
||||||
|
|
||||||
|
buildAppList() {
|
||||||
|
let apps = APP_LIST;
|
||||||
|
|
||||||
|
// Platform filter
|
||||||
|
if (this.state.platform !== Platform.All) {
|
||||||
|
apps = apps.filter(a => a.platforms.includes(this.state.platform));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({ apps });
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -159,12 +157,44 @@ export class Apps extends Component<any, any> {
|
||||||
<meta property={"title"} content={title} />
|
<meta property={"title"} content={title} />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<TitleBlock />
|
<TitleBlock />
|
||||||
<MobileAppsBlock />
|
{this.filterAndTitleBlock()}
|
||||||
<WebAppsBlock />
|
<AppGrid apps={this.state.apps} />
|
||||||
<CliAppsBlock />
|
|
||||||
<ApiLibrariesBlock />
|
<ApiLibrariesBlock />
|
||||||
<BottomSpacer />
|
<BottomSpacer />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filterAndTitleBlock() {
|
||||||
|
return (
|
||||||
|
<div id="search">
|
||||||
|
<div className="flex flex-row flex-wrap gap-4 mb-4">
|
||||||
|
<div className="flex-none"></div>
|
||||||
|
<div className="grow"></div>
|
||||||
|
<div>
|
||||||
|
<select
|
||||||
|
className={`${SELECT_CLASSES} mr-2`}
|
||||||
|
value={this.state.platform}
|
||||||
|
onChange={linkEvent(this, handlePlatformChange)}
|
||||||
|
name="platform_select"
|
||||||
|
>
|
||||||
|
{Object.entries(Platform).map(([name, platform]) => (
|
||||||
|
<option key={name} value={platform}>
|
||||||
|
{i18n.t(platform as string as I18nKeys)}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handlePlatformChange(i: Apps, event: any) {
|
||||||
|
let platform: Platform = (event.target.value as Platform) ?? Platform.All;
|
||||||
|
i.setState({
|
||||||
|
platform,
|
||||||
|
});
|
||||||
|
i.buildAppList();
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,3 +142,7 @@ export const DonateBlock = () => (
|
||||||
);
|
);
|
||||||
|
|
||||||
export const BottomSpacer = () => <div className="pb-32" />;
|
export const BottomSpacer = () => <div className="pb-32" />;
|
||||||
|
|
||||||
|
export const SectionTitle = ({ title }) => (
|
||||||
|
<div className="text-2xl mb-3">{title}</div>
|
||||||
|
);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { Component, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { All_TOPIC, TOPICS, Topic } from "./instances-definitions";
|
import { ALL_TOPIC, TOPICS, Topic } from "./instances-definitions";
|
||||||
import { LANGUAGES, i18n } from "../i18next";
|
import { LANGUAGES, i18n } from "../i18next";
|
||||||
import { I18nKeys } from "i18next";
|
import { I18nKeys } from "i18next";
|
||||||
import { Icon } from "./icon";
|
import { Icon } from "./icon";
|
||||||
|
@ -120,14 +120,14 @@ export class InstancePicker extends Component<Props, State> {
|
||||||
|
|
||||||
function handleTopicChange(i: InstancePicker, event: any) {
|
function handleTopicChange(i: InstancePicker, event: any) {
|
||||||
i.setState({
|
i.setState({
|
||||||
topic: TOPICS.find(c => c.name == event.target.value) ?? All_TOPIC,
|
topic: TOPICS.find(c => c.name == event.target.value) ?? ALL_TOPIC,
|
||||||
activeStep: Step.Language,
|
activeStep: Step.Language,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleLanguageChange(i: InstancePicker, event: any) {
|
function handleLanguageChange(i: InstancePicker, event: any) {
|
||||||
i.setState({ language: event.target.value });
|
i.setState({ language: event.target.value });
|
||||||
const url = `/instances?topic=${i.state.topic?.name ?? All_TOPIC}&language=${
|
const url = `/instances?topic=${i.state.topic?.name ?? ALL_TOPIC}&language=${
|
||||||
i.state.language
|
i.state.language
|
||||||
}&scroll=true`;
|
}&scroll=true`;
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ export interface Topic {
|
||||||
icon: string;
|
icon: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const All_TOPIC: Topic = {
|
export const ALL_TOPIC: Topic = {
|
||||||
name: "all_topics",
|
name: "all_topics",
|
||||||
icon: "folder",
|
icon: "folder",
|
||||||
};
|
};
|
||||||
|
@ -88,7 +88,7 @@ const SPORTS: Topic = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TOPICS: Topic[] = [
|
export const TOPICS: Topic[] = [
|
||||||
All_TOPIC,
|
ALL_TOPIC,
|
||||||
GENERAL,
|
GENERAL,
|
||||||
TECHNOLOGY,
|
TECHNOLOGY,
|
||||||
POLITICS,
|
POLITICS,
|
||||||
|
|
|
@ -4,12 +4,12 @@ import { i18n, LANGUAGES } from "../i18next";
|
||||||
import { T } from "inferno-i18next";
|
import { T } from "inferno-i18next";
|
||||||
import { instance_stats } from "../instance_stats";
|
import { instance_stats } from "../instance_stats";
|
||||||
import { getQueryParams, mdToHtml, numToSI } from "../utils";
|
import { getQueryParams, mdToHtml, numToSI } from "../utils";
|
||||||
import { Badge, SELECT_CLASSES, TEXT_GRADIENT } from "./common";
|
import { Badge, SELECT_CLASSES, SectionTitle, TEXT_GRADIENT } from "./common";
|
||||||
import {
|
import {
|
||||||
INSTANCE_HELPERS,
|
INSTANCE_HELPERS,
|
||||||
Topic,
|
Topic,
|
||||||
RECOMMENDED_INSTANCES,
|
RECOMMENDED_INSTANCES,
|
||||||
All_TOPIC,
|
ALL_TOPIC,
|
||||||
TOPICS,
|
TOPICS,
|
||||||
} from "./instances-definitions";
|
} from "./instances-definitions";
|
||||||
import { Icon, IconSize } from "./icon";
|
import { Icon, IconSize } from "./icon";
|
||||||
|
@ -80,10 +80,6 @@ const ComparisonBlock = () => (
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const SectionTitle = ({ title }) => (
|
|
||||||
<div className="text-2xl mb-3">{title}</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
interface InstanceCardGridProps {
|
interface InstanceCardGridProps {
|
||||||
title: string;
|
title: string;
|
||||||
instances: any[];
|
instances: any[];
|
||||||
|
@ -367,7 +363,7 @@ function getSortFromQuery(sort?: string): Sort {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTopicFromQuery(topic?: string): Topic {
|
function getTopicFromQuery(topic?: string): Topic {
|
||||||
return TOPICS.find(c => c.name == topic) ?? All_TOPIC;
|
return TOPICS.find(c => c.name == topic) ?? ALL_TOPIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getInstancesQueryParams() {
|
function getInstancesQueryParams() {
|
||||||
|
@ -384,7 +380,7 @@ export class Instances extends Component<Props, State> {
|
||||||
instances: [],
|
instances: [],
|
||||||
sort: RANDOM_SORT,
|
sort: RANDOM_SORT,
|
||||||
language: "all",
|
language: "all",
|
||||||
topic: All_TOPIC,
|
topic: ALL_TOPIC,
|
||||||
scroll: false,
|
scroll: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -434,7 +430,7 @@ export class Instances extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Topic filter
|
// Topic filter
|
||||||
if (this.state.topic !== All_TOPIC) {
|
if (this.state.topic !== ALL_TOPIC) {
|
||||||
const topicRecs = recommended.filter(r =>
|
const topicRecs = recommended.filter(r =>
|
||||||
r.topics.includes(this.state.topic),
|
r.topics.includes(this.state.topic),
|
||||||
);
|
);
|
||||||
|
@ -565,7 +561,7 @@ function handleSortChange(i: Instances, event: any) {
|
||||||
|
|
||||||
function handleTopicChange(i: Instances, event: any) {
|
function handleTopicChange(i: Instances, event: any) {
|
||||||
i.setState({
|
i.setState({
|
||||||
topic: TOPICS.find(c => c.name == event.target.value) ?? All_TOPIC,
|
topic: TOPICS.find(c => c.name == event.target.value) ?? ALL_TOPIC,
|
||||||
});
|
});
|
||||||
i.buildInstanceList();
|
i.buildInstanceList();
|
||||||
}
|
}
|
||||||
|
@ -579,7 +575,7 @@ function handleSeeAll(i: Instances) {
|
||||||
i.setState({
|
i.setState({
|
||||||
sort: RANDOM_SORT,
|
sort: RANDOM_SORT,
|
||||||
language: "all",
|
language: "all",
|
||||||
topic: All_TOPIC,
|
topic: ALL_TOPIC,
|
||||||
});
|
});
|
||||||
i.buildInstanceList();
|
i.buildInstanceList();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue