From 3a4d3e941c5dd147b30c48ce140208e38ca7bf37 Mon Sep 17 00:00:00 2001
From: Jonas Heinrich <onny@project-insanity.org>
Date: Sun, 13 Dec 2020 18:13:59 +0100
Subject: [PATCH] add category name, fix linking author, categories and
 episodes

---
 package-lock.json             |  16 +
 package.json                  |   1 +
 src/App.vue                   |  45 ++-
 src/assets/categories.json    | 707 ++++++++++++++++++++++++++++++++++
 src/components/Navigation.vue |   2 +-
 src/components/Table.vue      |  82 +++-
 src/main.js                   |   4 +-
 src/services/player.js        |  39 ++
 src/services/podcastApi.js    |  20 +
 src/views/Episode.vue         |  49 ---
 src/views/Show.vue            | 244 +++++-------
 11 files changed, 997 insertions(+), 212 deletions(-)
 create mode 100644 src/assets/categories.json
 create mode 100644 src/services/player.js
 create mode 100644 src/services/podcastApi.js

diff --git a/package-lock.json b/package-lock.json
index 5e1d672..6aa4a66 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11403,6 +11403,22 @@
 			"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.4.9.tgz",
 			"integrity": "sha512-CGAKWN44RqXW06oC+u4mPgHLQQi2t6vLD/JbGRDAXm0YpMv0bgpKuU5bBd7AvMgfTz9kXVRIWKHqRwGEb8xFkA=="
 		},
+		"vue-show-more-text": {
+			"version": "2.0.2",
+			"resolved": "https://registry.npmjs.org/vue-show-more-text/-/vue-show-more-text-2.0.2.tgz",
+			"integrity": "sha512-x/WuikWAx8Hm4gpZx6KHtJYiXDordGdSoXrd34lTiJeAnlT8Y7Yc0FfGBNdUv6mXncuET3LiRwwNz+X5gI+oiw==",
+			"requires": {
+				"core-js": "^3.6.5",
+				"vue": "^2.6.11"
+			},
+			"dependencies": {
+				"core-js": {
+					"version": "3.8.1",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.1.tgz",
+					"integrity": "sha512-9Id2xHY1W7m8hCl8NkhQn5CufmF/WuR30BTRewvCXc1aZd3kMECwNZ69ndLbekKfakw9Rf2Xyc+QR6E7Gg+obg=="
+				}
+			}
+		},
 		"vue-style-loader": {
 			"version": "4.1.2",
 			"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz",
diff --git a/package.json b/package.json
index e7c6b83..d173c44 100644
--- a/package.json
+++ b/package.json
@@ -48,6 +48,7 @@
 		"vue-clipboard2": "^0.3.1",
 		"vue-resize-observer": "^1.0.32",
 		"vue-router": "^3.4.9",
+		"vue-show-more-text": "^2.0.2",
 		"vuex": "^3.5.1"
 	},
 	"browserslist": [
diff --git a/src/App.vue b/src/App.vue
index 553a857..6df74e8 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -21,5 +21,48 @@
   -->
 
 <template>
-	<router-view />
+	<Content app-name="podcast">
+		<Navigation />
+		<AppContent>
+			<router-view />
+		</AppContent>
+	</Content>
 </template>
+
+<script>
+import Content from '@nextcloud/vue/dist/Components/Content'
+import AppContent from '@nextcloud/vue/dist/Components/AppContent'
+import Navigation from './components/Navigation'
+
+export default {
+	name: 'App',
+	components: {
+		Content,
+		Navigation,
+		AppContent,
+	},
+	created() {
+		this.loadSettings()
+	},
+	methods: {
+		loadSettings() {
+
+			// axios.defaults.headers.common = {
+			// 'User-Agent': 'Nextcloud Podcast App/' + this.$version,
+			// }
+			this.$store.dispatch('getVolumeState')
+
+		},
+	},
+}
+</script>
+
+<style lang="scss">
+
+@media only screen and (min-width: 1024px) {
+	.app-navigation-toggle {
+		display: none;
+	}
+}
+
+</style>
diff --git a/src/assets/categories.json b/src/assets/categories.json
new file mode 100644
index 0000000..e04a054
--- /dev/null
+++ b/src/assets/categories.json
@@ -0,0 +1,707 @@
+{
+    "status": 1,
+    "msg": "ok",
+    "meta": {
+        "API_INFO": {
+            "API_VERSION": "0.2"
+        },
+        "SERVER": "2a01:4f8:1c0c:7bfd::1",
+        "duration": 0
+    },
+    "data": [
+        {
+            "id": 100,
+            "slug": "arts",
+            "name": "Arts",
+            "name_de": "Kunst",
+            "subcategories": [
+                {
+                    "id": 102,
+                    "slug": "books",
+                    "name": "Books",
+                    "name_de": "B\u00fccher"
+                },
+                {
+                    "id": 103,
+                    "slug": "design",
+                    "name": "Design",
+                    "name_de": "Design"
+                },
+                {
+                    "id": 104,
+                    "slug": "fashion-beauty",
+                    "name": "Fashion & Beauty",
+                    "name_de": "Mode & Sch\u00f6nheit"
+                },
+                {
+                    "id": 105,
+                    "slug": "food",
+                    "name": "Food",
+                    "name_de": "Lebensmittel"
+                },
+                {
+                    "id": 106,
+                    "slug": "performing-arts",
+                    "name": "Performing Arts",
+                    "name_de": "Darstellende Kunst"
+                },
+                {
+                    "id": 107,
+                    "slug": "visual-arts",
+                    "name": "Visual Arts",
+                    "name_de": "Bildende Kunst"
+                }
+            ]
+        },
+        {
+            "id": 108,
+            "slug": "business",
+            "name": "Business",
+            "name_de": "Wirtschaft",
+            "subcategories": [
+                {
+                    "id": 109,
+                    "slug": "careers",
+                    "name": "Careers",
+                    "name_de": "Karriere"
+                },
+                {
+                    "id": 110,
+                    "slug": "entrepreneurship",
+                    "name": "Entrepreneurship",
+                    "name_de": "Unternehmertum"
+                },
+                {
+                    "id": 111,
+                    "slug": "investing",
+                    "name": "Investing",
+                    "name_de": "Investitionen"
+                },
+                {
+                    "id": 112,
+                    "slug": "management",
+                    "name": "Management",
+                    "name_de": "Unternehmensf\u00fchrung"
+                },
+                {
+                    "id": 113,
+                    "slug": "marketing",
+                    "name": "Marketing",
+                    "name_de": "Marketing"
+                },
+                {
+                    "id": 114,
+                    "slug": "non-profit",
+                    "name": "Non-profit",
+                    "name_de": "Gemeinn\u00fctzig"
+                }
+            ]
+        },
+        {
+            "id": 115,
+            "slug": "comedy",
+            "name": "Comedy",
+            "name_de": "Comedy",
+            "subcategories": [
+                {
+                    "id": 116,
+                    "slug": "comedy-interviews",
+                    "name": "Comedy Interviews",
+                    "name_de": "Interviews"
+                },
+                {
+                    "id": 117,
+                    "slug": "improv",
+                    "name": "Improv",
+                    "name_de": "Improvisation"
+                },
+                {
+                    "id": 118,
+                    "slug": "standup",
+                    "name": "Standup",
+                    "name_de": "Stand-Up"
+                }
+            ]
+        },
+        {
+            "id": 119,
+            "slug": "education",
+            "name": "Education",
+            "name_de": "Bildung",
+            "subcategories": [
+                {
+                    "id": 120,
+                    "slug": "courses",
+                    "name": "Courses",
+                    "name_de": "Sprachkurse"
+                },
+                {
+                    "id": 121,
+                    "slug": "how-to",
+                    "name": "How to",
+                    "name_de": "Anleitung"
+                },
+                {
+                    "id": 122,
+                    "slug": "language-learning",
+                    "name": "Language Learning",
+                    "name_de": "Sprache lernen"
+                },
+                {
+                    "id": 123,
+                    "slug": "self-improvement",
+                    "name": "Self Improvement",
+                    "name_de": "Selbstentwicklung"
+                }
+            ]
+        },
+        {
+            "id": 124,
+            "slug": "fiction",
+            "name": "Fiction",
+            "name_de": "Fiktion",
+            "subcategories": [
+                {
+                    "id": 125,
+                    "slug": "comedy-fiction",
+                    "name": "Comedy Fiction",
+                    "name_de": "Fiktion-Comedy"
+                },
+                {
+                    "id": 126,
+                    "slug": "drama",
+                    "name": "Drama",
+                    "name_de": "Drama"
+                },
+                {
+                    "id": 127,
+                    "slug": "science-fiction",
+                    "name": "Science Fiction",
+                    "name_de": "Science-Fiction"
+                }
+            ]
+        },
+        {
+            "id": 128,
+            "slug": "government",
+            "name": "Government",
+            "name_de": "Regierung",
+            "subcategories": []
+        },
+        {
+            "id": 129,
+            "slug": "history",
+            "name": "History",
+            "name_de": "Geschichte",
+            "subcategories": []
+        },
+        {
+            "id": 130,
+            "slug": "health-fitness",
+            "name": "Health & Fitness",
+            "name_de": "Gesundheit & Fitness",
+            "subcategories": [
+                {
+                    "id": 131,
+                    "slug": "alternative-health",
+                    "name": "Alternative Health",
+                    "name_de": "Alternative Gesundheit"
+                },
+                {
+                    "id": 132,
+                    "slug": "fitness",
+                    "name": "Fitness",
+                    "name_de": "Fitness"
+                },
+                {
+                    "id": 133,
+                    "slug": "medicine",
+                    "name": "Medicine",
+                    "name_de": "Medizin"
+                },
+                {
+                    "id": 134,
+                    "slug": "mental-health",
+                    "name": "Mental Health",
+                    "name_de": "Psychische Gesundheit"
+                },
+                {
+                    "id": 135,
+                    "slug": "nutrition",
+                    "name": "Nutrition",
+                    "name_de": "Ern\u00e4hrung"
+                },
+                {
+                    "id": 136,
+                    "slug": "sexuality",
+                    "name": "Sexuality",
+                    "name_de": "Sexualit\u00e4t"
+                }
+            ]
+        },
+        {
+            "id": 137,
+            "slug": "kids-family",
+            "name": "Kids & Family",
+            "name_de": "Kinder & Familie",
+            "subcategories": [
+                {
+                    "id": 138,
+                    "slug": "education-for-kids",
+                    "name": "Education for Kids",
+                    "name_de": "Bildung f\u00fcr Kinder"
+                },
+                {
+                    "id": 139,
+                    "slug": "parenting",
+                    "name": "Parenting",
+                    "name_de": "Erziehung"
+                },
+                {
+                    "id": 140,
+                    "slug": "pets-animals",
+                    "name": "Pets & Animals",
+                    "name_de": "Haustiere"
+                },
+                {
+                    "id": 141,
+                    "slug": "stories-for-kids",
+                    "name": "Stories for Kids",
+                    "name_de": "Geschichten f\u00fcr Kinder"
+                }
+            ]
+        },
+        {
+            "id": 142,
+            "slug": "leisure",
+            "name": "Leisure",
+            "name_de": "Freizeit",
+            "subcategories": [
+                {
+                    "id": 143,
+                    "slug": "animation-manga",
+                    "name": "Animation & Manga",
+                    "name_de": "Animation & Manga"
+                },
+                {
+                    "id": 144,
+                    "slug": "automotive",
+                    "name": "Automotive",
+                    "name_de": "Auto"
+                },
+                {
+                    "id": 145,
+                    "slug": "aviation",
+                    "name": "Aviation",
+                    "name_de": "Luftfahrt"
+                },
+                {
+                    "id": 146,
+                    "slug": "crafts",
+                    "name": "Crafts",
+                    "name_de": "Handwerk"
+                },
+                {
+                    "id": 147,
+                    "slug": "games",
+                    "name": "Games",
+                    "name_de": "Spiele"
+                },
+                {
+                    "id": 148,
+                    "slug": "hobbies",
+                    "name": "Hobbies",
+                    "name_de": "Hobbies"
+                },
+                {
+                    "id": 149,
+                    "slug": "home-garden",
+                    "name": "Home & Garden",
+                    "name_de": "Haus & Garten"
+                },
+                {
+                    "id": 150,
+                    "slug": "video-games",
+                    "name": "Video Games",
+                    "name_de": "Videospiele"
+                }
+            ]
+        },
+        {
+            "id": 151,
+            "slug": "music",
+            "name": "Music",
+            "name_de": "Musik",
+            "subcategories": [
+                {
+                    "id": 152,
+                    "slug": "music-commentary",
+                    "name": "Music Commentary",
+                    "name_de": "Musik-Kommentare"
+                },
+                {
+                    "id": 153,
+                    "slug": "music-history",
+                    "name": "Music History",
+                    "name_de": "Musik-Geschichte"
+                },
+                {
+                    "id": 154,
+                    "slug": "music-interviews",
+                    "name": "Music Interviews",
+                    "name_de": "Musik-Interviews"
+                }
+            ]
+        },
+        {
+            "id": 155,
+            "slug": "news",
+            "name": "News",
+            "name_de": "Nachrichten",
+            "subcategories": [
+                {
+                    "id": 156,
+                    "slug": "business-news",
+                    "name": "Business News",
+                    "name_de": "Gesch\u00e4ftsnachrichten"
+                },
+                {
+                    "id": 157,
+                    "slug": "daily-news",
+                    "name": "Daily News",
+                    "name_de": "T\u00e4gliche Nachrichten"
+                },
+                {
+                    "id": 158,
+                    "slug": "entertainment-news",
+                    "name": "Entertainment News",
+                    "name_de": "Unterhaltungsnachrichten"
+                },
+                {
+                    "id": 159,
+                    "slug": "news-commentary",
+                    "name": "News Commentary",
+                    "name_de": "Nachrichtenkommentare"
+                },
+                {
+                    "id": 160,
+                    "slug": "politics",
+                    "name": "Politics",
+                    "name_de": "Politik"
+                },
+                {
+                    "id": 161,
+                    "slug": "sports-news",
+                    "name": "Sports News",
+                    "name_de": "Sportnachrichten"
+                },
+                {
+                    "id": 162,
+                    "slug": "tech-news",
+                    "name": "Tech News",
+                    "name_de": "Techniknachrichten"
+                }
+            ]
+        },
+        {
+            "id": 163,
+            "slug": "religion-spirituality",
+            "name": "Religion & Spirituality",
+            "name_de": "Religion & Spiritualit\u00e4t",
+            "subcategories": [
+                {
+                    "id": 164,
+                    "slug": "buddhism",
+                    "name": "Buddhism",
+                    "name_de": "Buddhismus"
+                },
+                {
+                    "id": 165,
+                    "slug": "christianity",
+                    "name": "Christianity",
+                    "name_de": "Christentum"
+                },
+                {
+                    "id": 166,
+                    "slug": "hinduism",
+                    "name": "Hinduism",
+                    "name_de": "Hinduismus"
+                },
+                {
+                    "id": 167,
+                    "slug": "islam",
+                    "name": "Islam",
+                    "name_de": "Islam"
+                },
+                {
+                    "id": 168,
+                    "slug": "judaism",
+                    "name": "Judaism",
+                    "name_de": "Judentum"
+                },
+                {
+                    "id": 169,
+                    "slug": "religion",
+                    "name": "Religion",
+                    "name_de": "Religion"
+                },
+                {
+                    "id": 170,
+                    "slug": "spirituality",
+                    "name": "Spirituality",
+                    "name_de": "Spiritualit\u00e4t"
+                }
+            ]
+        },
+        {
+            "id": 171,
+            "slug": "science",
+            "name": "Science",
+            "name_de": "Wissenschaft",
+            "subcategories": [
+                {
+                    "id": 172,
+                    "slug": "astronomy",
+                    "name": "Astronomy",
+                    "name_de": "Astronomie"
+                },
+                {
+                    "id": 173,
+                    "slug": "chemistry",
+                    "name": "Chemistry",
+                    "name_de": "Chemie"
+                },
+                {
+                    "id": 174,
+                    "slug": "earth-sciences",
+                    "name": "Earth Sciences",
+                    "name_de": "Geologie"
+                },
+                {
+                    "id": 175,
+                    "slug": "life-sciences",
+                    "name": "Life Sciences",
+                    "name_de": "Biologie"
+                },
+                {
+                    "id": 176,
+                    "slug": "mathematics",
+                    "name": "Mathematics",
+                    "name_de": "Mathematik"
+                },
+                {
+                    "id": 177,
+                    "slug": "natural-sciences",
+                    "name": "Natural Sciences",
+                    "name_de": "Naturwissenschaft"
+                },
+                {
+                    "id": 178,
+                    "slug": "nature",
+                    "name": "Nature",
+                    "name_de": "Natur"
+                },
+                {
+                    "id": 179,
+                    "slug": "physics",
+                    "name": "Physics",
+                    "name_de": "Physik"
+                },
+                {
+                    "id": 180,
+                    "slug": "social-sciences",
+                    "name": "Social Sciences",
+                    "name_de": "Sozialwissenschaften"
+                }
+            ]
+        },
+        {
+            "id": 181,
+            "slug": "society-culture",
+            "name": "Society & Culture",
+            "name_de": "Gesellschaft & Kultur",
+            "subcategories": [
+                {
+                    "id": 182,
+                    "slug": "documentary",
+                    "name": "Documentary",
+                    "name_de": "Dokumentation"
+                },
+                {
+                    "id": 183,
+                    "slug": "personal-journals",
+                    "name": "Personal Journals",
+                    "name_de": "Tageb\u00fccher"
+                },
+                {
+                    "id": 184,
+                    "slug": "philosophy",
+                    "name": "Philosophy",
+                    "name_de": "Philosophie"
+                },
+                {
+                    "id": 185,
+                    "slug": "places-travel",
+                    "name": "Places & Travel",
+                    "name_de": "Orte & Reisen"
+                },
+                {
+                    "id": 186,
+                    "slug": "relationships",
+                    "name": "Relationships",
+                    "name_de": "Beziehungen"
+                }
+            ]
+        },
+        {
+            "id": 187,
+            "slug": "sports",
+            "name": "Sports",
+            "name_de": "Sport",
+            "subcategories": [
+                {
+                    "id": 188,
+                    "slug": "baseball",
+                    "name": "Baseball",
+                    "name_de": "Baseball"
+                },
+                {
+                    "id": 189,
+                    "slug": "basketball",
+                    "name": "Basketball",
+                    "name_de": "Basketball"
+                },
+                {
+                    "id": 190,
+                    "slug": "cricket",
+                    "name": "Cricket",
+                    "name_de": "Kricket"
+                },
+                {
+                    "id": 191,
+                    "slug": "fantasy-sports",
+                    "name": "Fantasy Sports",
+                    "name_de": "Fantasiesport"
+                },
+                {
+                    "id": 192,
+                    "slug": "football",
+                    "name": "Football",
+                    "name_de": "Football"
+                },
+                {
+                    "id": 193,
+                    "slug": "golf",
+                    "name": "Golf",
+                    "name_de": "Golf"
+                },
+                {
+                    "id": 194,
+                    "slug": "hockey",
+                    "name": "Hockey",
+                    "name_de": "Hockey"
+                },
+                {
+                    "id": 195,
+                    "slug": "rugby",
+                    "name": "Rugby",
+                    "name_de": "Rugby"
+                },
+                {
+                    "id": 196,
+                    "slug": "running",
+                    "name": "Running",
+                    "name_de": "Laufen"
+                },
+                {
+                    "id": 197,
+                    "slug": "soccer",
+                    "name": "Soccer",
+                    "name_de": "Fu\u00dfball"
+                },
+                {
+                    "id": 198,
+                    "slug": "swimming",
+                    "name": "Swimming",
+                    "name_de": "Schwimmen"
+                },
+                {
+                    "id": 199,
+                    "slug": "tennis",
+                    "name": "Tennis",
+                    "name_de": "Tennis"
+                },
+                {
+                    "id": 200,
+                    "slug": "volleyball",
+                    "name": "Volleyball",
+                    "name_de": "Volleyball"
+                },
+                {
+                    "id": 201,
+                    "slug": "wilderness",
+                    "name": "Wilderness",
+                    "name_de": "Wildnis"
+                },
+                {
+                    "id": 202,
+                    "slug": "wrestling",
+                    "name": "Wrestling",
+                    "name_de": "Wrestling"
+                }
+            ]
+        },
+        {
+            "id": 203,
+            "slug": "technology",
+            "name": "Technology",
+            "name_de": "Technik",
+            "subcategories": []
+        },
+        {
+            "id": 204,
+            "slug": "true-crime",
+            "name": "True Crime",
+            "name_de": "Wahre Kriminalf\u00e4lle",
+            "subcategories": []
+        },
+        {
+            "id": 205,
+            "slug": "tv-film",
+            "name": "TV & Film",
+            "name_de": "TV & Film",
+            "subcategories": [
+                {
+                    "id": 206,
+                    "slug": "after-shows",
+                    "name": "After Shows",
+                    "name_de": "After Shows"
+                },
+                {
+                    "id": 207,
+                    "slug": "film-history",
+                    "name": "Film History",
+                    "name_de": "Filmgeschichte"
+                },
+                {
+                    "id": 208,
+                    "slug": "film-interviews",
+                    "name": "Film Interviews",
+                    "name_de": "Filminterviews"
+                },
+                {
+                    "id": 209,
+                    "slug": "film-reviews",
+                    "name": "Film Reviews",
+                    "name_de": "Filmrezensionen"
+                },
+                {
+                    "id": 210,
+                    "slug": "tv-reviews",
+                    "name": "TV Reviews",
+                    "name_de": "TV-Rezensionen"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/components/Navigation.vue b/src/components/Navigation.vue
index 9a2b541..e29273f 100644
--- a/src/components/Navigation.vue
+++ b/src/components/Navigation.vue
@@ -29,7 +29,7 @@
 				:title="t('podcast', 'Listening')" />
 			<AppNavigationItem
 				:to="{ name: 'LIBRARY' }"
-				icon="icon-files"
+				icon="icon-files-dark"
 				:title="t('podcast', 'Library')" />
 			<AppNavigationItem
 				:to="{ name: 'BROWSE' }"
diff --git a/src/components/Table.vue b/src/components/Table.vue
index f3f4d16..d4a4ddf 100644
--- a/src/components/Table.vue
+++ b/src/components/Table.vue
@@ -29,10 +29,10 @@
 					{{ t('podcast', 'Name') }}
 				</th>
 				<th class="actionColumn" />
-				<th style="width: 90px">
+				<th class="durationColumn" style="width: 90px">
 					{{ t('podcast', 'Duration') }}
 				</th>
-				<th style="width: 130px">
+				<th class="dateColumn" style="width: 130px">
 					{{ t('podcast', 'Date') }}
 				</th>
 			</tr>
@@ -43,15 +43,21 @@
 				:key="idx"
 				:class="{ selected: idx === activeItem}">
 				<td class="iconColumn">
-					<blur-hash-image
-						width="64"
-						height="64"
-						hash="L1TSUA?bj[?b~qfQfQj[ayfQfQfQ"
-						:src="episode.imgURL" />
+					<div style="width: 64px; height: 64px;">
+						<blur-hash-image
+							hash="L1TSUA?bj[?b~qfQfQj[ayfQfQfQ"
+							:src="episode.imgURL" />
+					</div>
 				</td>
-				<td class="nameColumn">
+				<td
+					class="nameColumn"
+					@click="changeRoute(`/#/show/${episode.podcast_id}/${episode.id}`)">
 					<b>{{ episode.title }}</b>
-					<span>{{ episode.description }}</span>
+					<vue-show-more-text
+						:text="escapedEpisodeDescription(episode.description)"
+						:lines="2"
+						:has-more="false"
+						additional-container-css="padding: 0px;" />
 				</td>
 				<td class="actionColumn">
 					<Actions>
@@ -64,7 +70,7 @@
 						<ActionButton
 							icon="icon-info"
 							:close-after-click="true"
-							@click="changeRoute('/#/show/1084/5280308')">
+							@click="changeRoute(`/#/show/${episode.podcast_id}/${episode.id}`)">
 							{{ t('podcast', 'Show') }}
 						</ActionButton>
 						<ActionButton
@@ -80,10 +86,14 @@
 						</ActionButton>
 					</Actions>
 				</td>
-				<td>
+				<td
+					class="durationColumn"
+					@click="changeRoute(`/#/show/${episode.podcast_id}/${episode.id}`)">
 					{{ episode.duration_string }}
 				</td>
-				<td>
+				<td
+					class="dateColumn"
+					@click="changeRoute(`/#/show/${episode.podcast_id}/${episode.id}`)">
 					{{ readableTime(episode.inserted) }}
 				</td>
 			</tr>
@@ -96,6 +106,7 @@ import Actions from '@nextcloud/vue/dist/Components/Actions'
 import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
 import TimeAgo from 'javascript-time-ago'
 import en from 'javascript-time-ago/locale/en'
+import vueShowMoreText from 'vue-show-more-text'
 
 TimeAgo.addDefaultLocale(en)
 const timeAgo = new TimeAgo('en-US')
@@ -105,6 +116,7 @@ export default {
 	components: {
 		Actions,
 		ActionButton,
+		vueShowMoreText,
 	},
 	props: {
 		episodes: {
@@ -116,8 +128,12 @@ export default {
 		activeItem: null,
 	}),
 	methods: {
+		escapedEpisodeDescription(episodeDescription) {
+			episodeDescription = episodeDescription.replace(/\n/g, '')
+			return episodeDescription
+		},
 		readableTime(datetime) {
-			return timeAgo.format(Date.parse(datetime))
+			return timeAgo.format(Date.parse(datetime), 'twitter-minute-now')
 		},
 		downloadFile(episodeURL) {
 			window.open(episodeURL, 'download')
@@ -127,6 +143,7 @@ export default {
 			this.$emit('doPlay', episode)
 		},
 		changeRoute(path) {
+			console.log(path)
 			this.$router.push({ path })
 		},
 	},
@@ -159,9 +176,6 @@ table {
 			border-bottom: 1px solid var(--color-border);
 			padding: 15px;
 			height: 50px;
-		}
-
-		th, th a {
 			color: var(--color-text-maxcontrast);
 		}
 
@@ -240,4 +254,40 @@ table {
 
 }
 
+@media only screen and (max-width: 500px) {
+	table {
+		thead {
+			th.iconColumn {
+				width: 85px;
+			}
+			th.nameColumn {
+				padding-left: 0px;
+			}
+			th.actionColumn {
+				padding-left: 5px;
+				padding-right: 5px;
+				width: 50px;
+			}
+			th.durationColumn, th.dateColumn {
+				display: none;
+			}
+		}
+		tbody {
+			td.iconColumn {
+				padding-left: 10px;
+			}
+			td.nameColumn {
+				padding-left: 0px;
+			}
+			td.actionColumn {
+				padding-left: 5px;
+				padding-right: 5px;
+				width: 50px;
+			}
+			td.durationColumn, td.dateColumn {
+				display: none;
+			}
+		}
+	}
+}
 </style>
diff --git a/src/main.js b/src/main.js
index 5c0b4cc..6de012b 100644
--- a/src/main.js
+++ b/src/main.js
@@ -38,8 +38,8 @@ Vue.prototype.t = translate
 Vue.prototype.n = translatePlural
 Vue.prototype.OC = window.OC
 Vue.prototype.OCA = window.OCA
-Vue.prototype.$apiUrl = 'https://de1.api.radio-browser.info'
-Vue.prototype.$version = '1.0.1'
+Vue.prototype.$apiUrl = 'https://api.fyyd.de/0.2'
+Vue.prototype.$version = '0.0.1'
 
 Vue.use(VueClipboard)
 Vue.use(VueBlurHash)
diff --git a/src/services/player.js b/src/services/player.js
new file mode 100644
index 0000000..2e405db
--- /dev/null
+++ b/src/services/player.js
@@ -0,0 +1,39 @@
+import { Howl, Howler } from 'howler'
+import { showError } from '@nextcloud/dialogs'
+
+export let audioPlayer
+audioPlayer = null
+
+export function doPlay(episode) {
+	const vm = this
+
+	vm.$store.dispatch('isBuffering', true)
+
+	if (audioPlayer !== null) {
+		audioPlayer.fade(vm.player.volume, 0, 500)
+	}
+	vm.$store.dispatch('setTitle', episode.title)
+
+	Howler.unload()
+	audioPlayer = new Howl({
+		src: episode.enclosure,
+		html5: true,
+		volume: vm.player.volume,
+		onplay() {
+			vm.$store.dispatch('isPlaying', true)
+			vm.$store.dispatch('isBuffering', false)
+		},
+		onpause() {
+			vm.$store.dispatch('isPlaying', false)
+			vm.$store.dispatch('isBuffering', false)
+		},
+		onend() {
+			showError(t('podcast', 'Lost connection to podcast station, retrying ...'))
+			vm.$store.dispatch('isPlaying', false)
+			vm.$store.dispatch('isBuffering', true)
+		},
+	})
+	audioPlayer.unload()
+	audioPlayer.play()
+	audioPlayer.fade(0, vm.player.volume, 500)
+}
diff --git a/src/services/podcastApi.js b/src/services/podcastApi.js
new file mode 100644
index 0000000..ac0a5c6
--- /dev/null
+++ b/src/services/podcastApi.js
@@ -0,0 +1,20 @@
+const categories = require('../assets/categories.json')
+
+export function getCategoryName(categoryid) {
+	for (let i = 0; i < categories.data.length; i++) {
+		const obj = categories.data[i]
+		if (obj.id === categoryid) {
+			return obj.name
+		}
+		if ('subcategories' in categories.data[i]) {
+			const subcategories = categories.data[i].subcategories
+			for (let i = 0; i < subcategories.length; i++) {
+				const obj = subcategories[i]
+				if (obj.id === categoryid) {
+					return obj.name
+				}
+			}
+		}
+	}
+	return categoryid
+}
diff --git a/src/views/Episode.vue b/src/views/Episode.vue
index 52427c8..6cfd6ea 100644
--- a/src/views/Episode.vue
+++ b/src/views/Episode.vue
@@ -402,53 +402,4 @@ export default {
 	}
 }
 
-.podcastHeader {
-	width: 100%;
-	background: black;
-	min-height: 300px;
-	display: flex;
-	color: white;
-	justify-content: center;
-	padding: 40px 20px;
-	gap: 30px;
-
-	.podcastImage {
-		width: 230px;
-		height: 230px;
-		background: red;
-		background-size: cover;
-		background-position: center center;
-	}
-
-	.podcastDescription {
-		max-width: 500px;
-		max-height: 200px;
-		overflow: hidden;
-		text-overflow: ellipsis;
-		color: #ddd;
-
-		h1 {
-			font-size: 30px;
-			font-weight: bold;
-			line-height: 1.2em;
-			color: white;
-		}
-
-		.podcastAuthor {
-			padding-bottom: 10px;
-
-			a {
-				color: white;
-			}
-		}
-
-		ul.podcastCategory li {
-			padding: 5px;
-			background: red;
-		}
-
-	}
-
-}
-
 </style>
diff --git a/src/views/Show.vue b/src/views/Show.vue
index 88fa555..0216629 100644
--- a/src/views/Show.vue
+++ b/src/views/Show.vue
@@ -21,10 +21,10 @@
   -->
 
 <template>
-	<Content app-name="podcast">
-		<Navigation
-			:station-data="tableData" />
-		<AppContent>
+	<div>
+		<div
+			class="podcastHeaderBg"
+			:style="{ backgroundImage: `url(${podcast.smallImageURL})` }">
 			<div class="podcastHeader">
 				<div
 					class="podcastImage"
@@ -32,70 +32,60 @@
 				<div class="podcastDescription">
 					<h1>{{ podcast.title }}</h1>
 					<div class="podcastAuthor">
-						by <a href="#">{{ podcast.author }}</a>
+						by <a :href="`#/browse/author/${podcast.author}`">{{ podcast.author }}</a>
 					</div>
-					<div style="height: 40px; overflow: hidden; padding-bottom: 5px;">
-						{{ podcast.description }}
+					<div class="podcastControls">
+						<a href="#" class="button">Subscribe</a>
+						<ul class="podcastCategory">
+							<a v-for="(category, idx) in podcast.categories"
+								:key="idx"
+								:href="`#/browse/category/${podcast.categories[idx]}`">
+								<li>
+									{{ getCategoryName(podcast.categories[idx]) }}
+								</li>
+							</a>
+						</ul>
 					</div>
-					<ul class="podcastCategory">
-						<li
-							v-for="(category, idx) in podcast.categories"
-							:key="idx">
-							{{ podcast.categories[idx] }}
-						</li>
-					</ul>
-					<Actions default-icon="icon-add-white" :primary="true" menu-title="Subscribe" />
+					<vue-show-more-text
+						:text="podcast.description"
+						additional-container-css="padding: 0px;" />
 				</div>
 			</div>
-			<Table
-				v-show="!pageLoading && podcast.episodes.length > 0"
-				v-resize="onResize"
-				:episodes="podcast.episodes"
-				@doPlay="doPlay" />
-			<EmptyContent
-				v-if="pageLoading"
-				icon="icon-loading" />
-			<EmptyContent
-				v-if="tableData.length === 0 && !pageLoading"
-				:icon="emptyContentIcon">
-				{{ emptyContentMessage }}
-				<template #desc>
-					{{ emptyContentDesc }}
-				</template>
-			</EmptyContent>
-		</AppContent>
-	</Content>
+		</div>
+		<Table
+			v-show="!pageLoading && podcast.episodes.length > 0"
+			v-resize="onResize"
+			:episodes="podcast.episodes"
+			@doPlay="doPlay" />
+		<EmptyContent
+			v-if="pageLoading"
+			icon="icon-loading" />
+	</div>
 </template>
 
 <script>
-import Content from '@nextcloud/vue/dist/Components/Content'
-import AppContent from '@nextcloud/vue/dist/Components/AppContent'
 import EmptyContent from '@nextcloud/vue/dist/Components/EmptyContent'
-import Actions from '@nextcloud/vue/dist/Components/Actions'
-import Navigation from '../components/Navigation'
 import Table from '../components/Table'
-import { Howl, Howler } from 'howler'
 
 import { showError } from '@nextcloud/dialogs'
 import axios from '@nextcloud/axios'
 
-let audioPlayer = null
+import vueShowMoreText from 'vue-show-more-text'
+
+import { audioPlayer, doPlay } from '../services/player'
+import { getCategoryName } from '../services/podcastApi'
 
 export default {
 	name: 'Show',
 	components: {
-		Navigation,
-		Content,
-		AppContent,
 		Table,
 		EmptyContent,
-		Actions,
+		vueShowMoreText,
 	},
 	data: () => ({
 		podcast: {
 			episodes: [],
 		},
-		tableData: [],
 		pageLoading: false,
 		queryParams: {},
 	}),
@@ -103,36 +93,6 @@ export default {
 		player() {
 			return this.$store.state.player
 		},
-		emptyContentMessage() {
-			if (this.$route.name === 'FAVORITES') {
-				return t('podcast', 'No favorites yet')
-			} else if (this.$route.name === 'RECENT') {
-				return t('podcast', 'No recent stations yet')
-			} else if (this.$route.name === 'SEARCH') {
-				return t('podcast', 'No search results')
-			}
-			return 'No stations here'
-		},
-		emptyContentIcon() {
-			if (this.$route.name === 'FAVORITES') {
-				return 'icon-star'
-			} else if (this.$route.name === 'RECENT') {
-				return 'icon-recent'
-			} else if (this.$route.name === 'SEARCH') {
-				return 'icon-search'
-			}
-			return 'icon-podcast'
-		},
-		emptyContentDesc() {
-			if (this.$route.name === 'FAVORITES') {
-				return t('podcast', 'Stations you mark as favorite will show up here')
-			} else if (this.$route.name === 'RECENT') {
-				return t('podcast', 'Stations you recently played will show up here')
-			} else if (this.$route.name === 'SEARCH') {
-				return t('podcast', 'No stations were found matching your search term')
-			}
-			return t('podcast', 'No stations here')
-		},
 	},
 	watch: {
 		$route: 'onRoute',
@@ -149,15 +109,18 @@ export default {
 			}
 		},
 	},
-	created() {
-		this.loadSettings()
-	},
 	mounted() {
-		this.onRoute()
+		this.pageLoading = true
+		const podcastId = this.$route.params.id
+		this.queryPodcast(podcastId)
 		this.scroll()
 	},
 	methods: {
 
+		getCategoryName(categoryid) {
+			return getCategoryName(categoryid)
+		},
+
 		onResize({ width, height }) {
 			const contentHeight = document.getElementById('app-content-vue').scrollHeight
 			const tableHeight = height
@@ -166,56 +129,20 @@ export default {
 			}
 		},
 
+		doPlay(episode) {
+			doPlay(episode)
+		},
+
 		preFill() {
 			const route = this.$route
 			console.log(route)
 			// this.queryPodcast(route.name)
 		},
 
-		async onRoute() {
-			this.tableData = []
-			this.pageLoading = true
-			const podcastId = this.$route.params.id
-			this.queryPodcast(podcastId)
-		},
-
 		/**
 			 * Start playing a podcast episode
 			 * @param {Object} episode Episode object
 			 */
-		async doPlay(episode) {
-			const vm = this
-
-			vm.$store.dispatch('isBuffering', true)
-
-			if (audioPlayer !== null) {
-				audioPlayer.fade(vm.player.volume, 0, 500)
-			}
-			vm.$store.dispatch('setTitle', episode.title)
-
-			Howler.unload()
-			audioPlayer = new Howl({
-				src: episode.enclosure,
-				html5: true,
-				volume: vm.player.volume,
-				onplay() {
-					vm.$store.dispatch('isPlaying', true)
-					vm.$store.dispatch('isBuffering', false)
-				},
-				onpause() {
-					vm.$store.dispatch('isPlaying', false)
-					vm.$store.dispatch('isBuffering', false)
-				},
-				onend() {
-					showError(t('podcast', 'Lost connection to podcast station, retrying ...'))
-					vm.$store.dispatch('isPlaying', false)
-					vm.$store.dispatch('isBuffering', true)
-				},
-			})
-			audioPlayer.unload()
-			audioPlayer.play()
-			audioPlayer.fade(0, vm.player.volume, 500)
-		},
 
 		async queryPodcast(podcastId) {
 
@@ -247,52 +174,48 @@ export default {
 					const route = this.$route
 					console.log(route)
 					// this.queryPodcast(route.name)
-		    }
+				    }
 			}
 		},
-		loadSettings() {
-
-			// axios.defaults.headers.common = {
-			// 'User-Agent': 'Nextcloud Podcast App/' + this.$version,
-			// }
-			this.$store.dispatch('getVolumeState')
-
-		},
-
 	},
 }
 </script>
 
 <style lang="scss">
 
-@media only screen and (min-width: 1024px) {
-	.app-navigation-toggle {
-		display: none;
-	}
+.podcastHeaderBg {
+	background-size: cover;
+	background-position: center;
 }
 
 .podcastHeader {
 	width: 100%;
-	background: black;
 	min-height: 300px;
 	display: flex;
 	color: white;
 	justify-content: center;
 	padding: 40px 20px;
-	gap: 30px;
+	/* gap: 30px; */
+	background-color: rgba(0, 0, 0, .7);
+	backdrop-filter: blur(8px);
+	text-shadow: 1px 1px 2px rgba(0,0,0,.5);
+
+	.button {
+		text-shadow: 0px 0px 0px;
+	}
 
 	.podcastImage {
-		width: 230px;
-		height: 230px;
+		width: 200px;
+		height: 200px;
 		background-size: cover;
-		background-position: center center;
+		background-position: center;
+		box-shadow: 0 4px 60px rgba(0,0,0,.5);
+		margin-right: 25px;
+		border-radius: 5px;
 	}
 
 	.podcastDescription {
 		max-width: 500px;
-		max-height: 200px;
-		overflow: hidden;
-		text-overflow: ellipsis;
 		color: #ddd;
 
 		h1 {
@@ -303,24 +226,59 @@ export default {
 		}
 
 		.podcastAuthor {
-			padding-bottom: 10px;
+			padding-bottom: 5px;
 
 			a {
 				color: white;
 			}
 		}
 
+		.podcastControls {
+			display: flex;
+			align-items: center;
+			margin-bottom: 5px;
+
+			.button {
+				margin-right: 10px;
+			}
+		}
+
 		ul.podcastCategory li {
-			color: var(--color-text-maxcontrast);
 			display: inline;
 			border: 1px solid var(--color-text-maxcontrast);
 			border-radius: var(--border-radius);
-			padding: 3px 6px;
 			margin-right: 5px;
+			cursor: pointer;
+			color: var(--color-text-maxcontrast);
+			padding: 3px 6px;
 		}
 
+		ul.podcastCategory li:hover {
+			border: 1px solid white;
+			color: white;
+		}
 	}
 
 }
 
+@media only screen and (max-width: 500px) {
+	.podcastHeader {
+		flex-direction: column;
+		align-items: center;
+
+		.podcastImage {
+			margin-right: 0px;
+			margin-bottom: 25px;
+		}
+
+		.podcastDescription {
+			text-align: center;
+
+			.podcastControls {
+				justify-content: center;
+			}
+		}
+	}
+}
+
 </style>
-- 
GitLab