Compare commits

..
135 changed files with 1643 additions and 148 deletions
+2 -1
View File
@@ -89,4 +89,5 @@ sw.*
# Vim swap files
*.swp
/resources/
/resources/
/android/app/release/
+6
View File
@@ -34,6 +34,7 @@ class Server extends EventEmitter {
this.user = user
this.store.commit('user/setUser', user)
if (user) {
this.store.commit('user/setSettings', user.settings)
localStorage.setItem('userToken', user.token)
} else {
localStorage.removeItem('userToken')
@@ -149,6 +150,11 @@ class Server extends EventEmitter {
this.emit('initialStream', data.stream)
}
})
this.socket.on('user_updated', (user) => {
if (this.user && user.id === this.user.id) {
this.setUser(user)
}
})
}
}
+3 -6
View File
@@ -1,6 +1,3 @@
//apply plugin: 'com.android.application'
//apply plugin: 'kotlin-android'
plugins {
id 'com.android.application'
id 'kotlin-android'
@@ -13,8 +10,8 @@ android {
applicationId "com.audiobookshelf.app"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
versionCode 5
versionName "0.2.1-beta"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
@@ -49,7 +46,7 @@ dependencies {
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
implementation project(':capacitor-cordova-android-plugins')
implementation "androidx.core:core-ktx:+"
implementation "androidx.core:core-ktx:1.6.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
+1 -1
View File
@@ -10,7 +10,7 @@ android {
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
dependencies {
implementation project(':capacitor-dialog')
implementation project(':capacitor-toast')
implementation project(':robingenz-capacitor-app-update')
}
@@ -4,7 +4,7 @@
"classpath": "com.capacitorjs.plugins.dialog.DialogPlugin"
},
{
"pkg": "@capacitor/toast",
"classpath": "com.capacitorjs.plugins.toast.ToastPlugin"
"pkg": "@robingenz/capacitor-app-update",
"classpath": "dev.robingenz.capacitor.appupdate.AppUpdatePlugin"
}
]
Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

@@ -13,6 +13,7 @@ class Audiobook {
var cover:String = ""
var playWhenReady:Boolean = false
var startTime:Long = 0
var playbackSpeed:Float = 1f
var duration:Long = 0
var hasPlayerLoaded:Boolean = false
@@ -30,6 +31,7 @@ class Audiobook {
playlistUrl = jsondata.getString("playlistUrl", "").toString()
playWhenReady = jsondata.getBoolean("playWhenReady", false) == true
startTime = jsondata.getString("startTime", "0")!!.toLong()
playbackSpeed = jsondata.getDouble("playbackSpeed")!!.toFloat()
duration = jsondata.getString("duration", "0")!!.toLong()
playlistUri = Uri.parse(playlistUrl)
@@ -102,16 +102,27 @@ class MyNativeAudio : Plugin() {
}
@PluginMethod
fun seekForward10(call: PluginCall) {
fun seekForward(call: PluginCall) {
var amount:Long = call.getString("amount", "0")!!.toLong()
Handler(Looper.getMainLooper()).post() {
playerNotificationService.seekForward10()
playerNotificationService.seekForward(amount)
call.resolve()
}
}
@PluginMethod
fun seekBackward10(call: PluginCall) {
fun seekBackward(call: PluginCall) {
var amount:Long = call.getString("amount", "0")!!.toLong()
Handler(Looper.getMainLooper()).post() {
playerNotificationService.seekBackward10()
playerNotificationService.seekBackward(amount)
call.resolve()
}
}
@PluginMethod
fun setPlaybackSpeed(call: PluginCall) {
var playbackSpeed:Float = call.getFloat("speed", 1.0f)!!
Handler(Looper.getMainLooper()).post() {
playerNotificationService.setPlaybackSpeed(playbackSpeed)
call.resolve()
}
}
@@ -191,6 +191,8 @@ class PlayerNotificationService : Service() {
playerNotificationManager.setUseChronometer(false)
playerNotificationManager.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
playerNotificationManager.setPriority(NotificationCompat.PRIORITY_MAX)
playerNotificationManager.setUseFastForwardActionInCompactView(true)
playerNotificationManager.setUseRewindActionInCompactView(true)
// Unknown action
playerNotificationManager.setBadgeIconType(NotificationCompat.BADGE_ICON_LARGE)
@@ -276,14 +278,6 @@ class PlayerNotificationService : Service() {
}
override fun onEvents(player: Player, events: Player.Events) {
if (events.contains(Player.EVENT_TRACKS_CHANGED)) {
Log.d(tag, "EVENT_TRACKS_CHANGED")
}
if (events.contains(Player.EVENT_TIMELINE_CHANGED)) {
Log.d(tag, "EVENT_TIMELINE_CHANGED")
}
if (events.contains(Player.EVENT_POSITION_DISCONTINUITY)) {
Log.d(tag, "EVENT_POSITION_DISCONTINUITY")
}
@@ -373,6 +367,7 @@ class PlayerNotificationService : Service() {
mPlayer.setMediaSource(mediaSource, true)
mPlayer.prepare()
mPlayer.playWhenReady = currentAudiobook!!.playWhenReady
mPlayer.setPlaybackSpeed(audiobook.playbackSpeed)
}
@@ -396,12 +391,16 @@ class PlayerNotificationService : Service() {
mPlayer.seekTo(time)
}
fun seekForward10() {
mPlayer.seekTo(mPlayer.currentPosition + 10000)
fun seekForward(amount:Long) {
mPlayer.seekTo(mPlayer.currentPosition + amount)
}
fun seekBackward10() {
mPlayer.seekTo(mPlayer.currentPosition - 10000)
fun seekBackward(amount:Long) {
mPlayer.seekTo(mPlayer.currentPosition - amount)
}
fun setPlaybackSpeed(speed:Float) {
mPlayer.setPlaybackSpeed(speed)
}
fun terminateStream() {
@@ -0,0 +1,21 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#FFFFFF">
<group android:scaleX="1.127451"
android:scaleY="1.127451"
android:translateX="-1.5294118"
android:translateY="-1.5294118">
<path
android:fillColor="@android:color/white"
android:pathData="M18,13c0,3.31 -2.69,6 -6,6s-6,-2.69 -6,-6s2.69,-6 6,-6v4l5,-5l-5,-5v4c-4.42,0 -8,3.58 -8,8c0,4.42 3.58,8 8,8s8,-3.58 8,-8H18z"/>
<path
android:fillColor="@android:color/white"
android:pathData="M10.86,15.94l0,-4.27l-0.09,0l-1.77,0.63l0,0.69l1.01,-0.31l0,3.26z"/>
<path
android:fillColor="@android:color/white"
android:pathData="M12.25,13.44v0.74c0,1.9 1.31,1.82 1.44,1.82c0.14,0 1.44,0.09 1.44,-1.82v-0.74c0,-1.9 -1.31,-1.82 -1.44,-1.82C13.55,11.62 12.25,11.53 12.25,13.44zM14.29,13.32v0.97c0,0.77 -0.21,1.03 -0.59,1.03c-0.38,0 -0.6,-0.26 -0.6,-1.03v-0.97c0,-0.75 0.22,-1.01 0.59,-1.01C14.07,12.3 14.29,12.57 14.29,13.32z"/>
</group>
</vector>
@@ -0,0 +1,21 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#FFFFFF">
<group android:scaleX="1.127451"
android:scaleY="1.127451"
android:translateX="-1.5294118"
android:translateY="-1.5294118">
<path
android:fillColor="@android:color/white"
android:pathData="M11.99,5V1l-5,5l5,5V7c3.31,0 6,2.69 6,6s-2.69,6 -6,6s-6,-2.69 -6,-6h-2c0,4.42 3.58,8 8,8s8,-3.58 8,-8S16.41,5 11.99,5z"/>
<path
android:fillColor="@android:color/white"
android:pathData="M10.89,16h-0.85v-3.26l-1.01,0.31v-0.69l1.77,-0.63h0.09V16z"/>
<path
android:fillColor="@android:color/white"
android:pathData="M15.17,14.24c0,0.32 -0.03,0.6 -0.1,0.82s-0.17,0.42 -0.29,0.57s-0.28,0.26 -0.45,0.33s-0.37,0.1 -0.59,0.1s-0.41,-0.03 -0.59,-0.1s-0.33,-0.18 -0.46,-0.33s-0.23,-0.34 -0.3,-0.57s-0.11,-0.5 -0.11,-0.82V13.5c0,-0.32 0.03,-0.6 0.1,-0.82s0.17,-0.42 0.29,-0.57s0.28,-0.26 0.45,-0.33s0.37,-0.1 0.59,-0.1s0.41,0.03 0.59,0.1c0.18,0.07 0.33,0.18 0.46,0.33s0.23,0.34 0.3,0.57s0.11,0.5 0.11,0.82V14.24zM14.32,13.38c0,-0.19 -0.01,-0.35 -0.04,-0.48s-0.07,-0.23 -0.12,-0.31s-0.11,-0.14 -0.19,-0.17s-0.16,-0.05 -0.25,-0.05s-0.18,0.02 -0.25,0.05s-0.14,0.09 -0.19,0.17s-0.09,0.18 -0.12,0.31s-0.04,0.29 -0.04,0.48v0.97c0,0.19 0.01,0.35 0.04,0.48s0.07,0.24 0.12,0.32s0.11,0.14 0.19,0.17s0.16,0.05 0.25,0.05s0.18,-0.02 0.25,-0.05s0.14,-0.09 0.19,-0.17s0.09,-0.19 0.11,-0.32s0.04,-0.29 0.04,-0.48V13.38z"/>
</group>
</vector>
Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 444 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 591 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 869 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 843 B

@@ -0,0 +1,7 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M18,13c0,3.31 -2.69,6 -6,6s-6,-2.69 -6,-6s2.69,-6 6,-6v4l5,-5l-5,-5v4c-4.42,0 -8,3.58 -8,8c0,4.42 3.58,8 8,8s8,-3.58 8,-8H18z"/>
<path android:fillColor="@android:color/white" android:pathData="M10.86,15.94l0,-4.27l-0.09,0l-1.77,0.63l0,0.69l1.01,-0.31l0,3.26z"/>
<path android:fillColor="@android:color/white" android:pathData="M12.25,13.44v0.74c0,1.9 1.31,1.82 1.44,1.82c0.14,0 1.44,0.09 1.44,-1.82v-0.74c0,-1.9 -1.31,-1.82 -1.44,-1.82C13.55,11.62 12.25,11.53 12.25,13.44zM14.29,13.32v0.97c0,0.77 -0.21,1.03 -0.59,1.03c-0.38,0 -0.6,-0.26 -0.6,-1.03v-0.97c0,-0.75 0.22,-1.01 0.59,-1.01C14.07,12.3 14.29,12.57 14.29,13.32z"/>
</vector>
@@ -0,0 +1,7 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M11.99,5V1l-5,5l5,5V7c3.31,0 6,2.69 6,6s-2.69,6 -6,6s-6,-2.69 -6,-6h-2c0,4.42 3.58,8 8,8s8,-3.58 8,-8S16.41,5 11.99,5z"/>
<path android:fillColor="@android:color/white" android:pathData="M10.89,16h-0.85v-3.26l-1.01,0.31v-0.69l1.77,-0.63h0.09V16z"/>
<path android:fillColor="@android:color/white" android:pathData="M15.17,14.24c0,0.32 -0.03,0.6 -0.1,0.82s-0.17,0.42 -0.29,0.57s-0.28,0.26 -0.45,0.33s-0.37,0.1 -0.59,0.1s-0.41,-0.03 -0.59,-0.1s-0.33,-0.18 -0.46,-0.33s-0.23,-0.34 -0.3,-0.57s-0.11,-0.5 -0.11,-0.82V13.5c0,-0.32 0.03,-0.6 0.1,-0.82s0.17,-0.42 0.29,-0.57s0.28,-0.26 0.45,-0.33s0.37,-0.1 0.59,-0.1s0.41,0.03 0.59,0.1c0.18,0.07 0.33,0.18 0.46,0.33s0.23,0.34 0.3,0.57s0.11,0.5 0.11,0.82V14.24zM14.32,13.38c0,-0.19 -0.01,-0.35 -0.04,-0.48s-0.07,-0.23 -0.12,-0.31s-0.11,-0.14 -0.19,-0.17s-0.16,-0.05 -0.25,-0.05s-0.18,0.02 -0.25,0.05s-0.14,0.09 -0.19,0.17s-0.09,0.18 -0.12,0.31s-0.04,0.29 -0.04,0.48v0.97c0,0.19 0.01,0.35 0.04,0.48s0.07,0.24 0.12,0.32s0.11,0.14 0.19,0.17s0.16,0.05 0.25,0.05s0.18,-0.02 0.25,-0.05s0.14,-0.09 0.19,-0.17s0.09,-0.19 0.11,-0.32s0.04,-0.29 0.04,-0.48V13.38z"/>
</vector>
Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<background android:drawable="@mipmap/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<background android:drawable="@mipmap/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 B

After

Width:  |  Height:  |  Size: 803 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 B

After

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 536 B

After

Width:  |  Height:  |  Size: 1011 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 923 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 15 KiB

+2 -2
View File
@@ -17,6 +17,6 @@
<style name="AppTheme.NoActionBarLaunch" parent="AppTheme.NoActionBar">
<item name="android:background">@drawable/splash</item>
<item name="android:background">@drawable/screen</item>
</style>
</resources>
</resources>
-9
View File
@@ -2,14 +2,5 @@
<widget version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<access origin="*" />
<feature name="File">
<param name="android-package" value="org.apache.cordova.file.FileUtils"/>
<param name="onload" value="true"/>
</feature>
<feature name="Media">
<param name="android-package" value="org.apache.cordova.media.AudioHandler"/>
</feature>
</widget>
+2 -2
View File
@@ -5,5 +5,5 @@ project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/
include ':capacitor-dialog'
project(':capacitor-dialog').projectDir = new File('../node_modules/@capacitor/dialog/android')
include ':capacitor-toast'
project(':capacitor-toast').projectDir = new File('../node_modules/@capacitor/toast/android')
include ':robingenz-capacitor-app-update'
project(':robingenz-capacitor-app-update').projectDir = new File('../node_modules/@robingenz/capacitor-app-update/android')
+3 -2
View File
@@ -5,7 +5,8 @@ ext {
androidxActivityVersion = '1.2.0'
androidxAppCompatVersion = '1.2.0'
androidxCoordinatorLayoutVersion = '1.1.0'
androidxCoreVersion = '1.3.2'
androidxCoreVersion = '1.6.0'
androidPlayCore = '1.9.0'
androidxFragmentVersion = '1.3.0'
junitVersion = '4.13.1'
androidxJunitVersion = '1.1.2'
@@ -13,7 +14,7 @@ ext {
cordovaAndroidVersion = '7.0.0'
androidx_app_compat_version = '1.2.0'
androidx_car_version = '1.0.0-alpha7'
androidx_core_ktx_version = '1.3.1'
androidx_core_ktx_version = '1.6.0'
androidx_media_version = '1.0.1'
androidx_preference_version = '1.1.1'
androidx_test_runner_version = '1.3.0'
+15
View File
@@ -0,0 +1,15 @@
.box-shadow-md {
box-shadow: 2px 8px 6px #111111aa;
}
.box-shadow-lg-up {
box-shadow: 0px -12px 8px #111111ee;
}
.box-shadow-xl {
box-shadow: 2px 14px 8px #111111aa;
}
.box-shadow-book {
box-shadow: 4px 1px 8px #11111166, -4px 1px 8px #11111166, 1px -4px 8px #11111166;
}
+22 -7
View File
@@ -16,8 +16,8 @@
<div class="cursor-pointer flex items-center justify-center text-gray-300" @mousedown.prevent @mouseup.prevent @click.stop="forward10">
<span class="material-icons text-3xl">forward_10</span>
</div>
<div class="cursor-pointer flex items-center justify-center text-gray-300 ml-8" @mousedown.prevent @mouseup.prevent>
<span class="font-mono text-lg uppercase">1x</span>
<div class="cursor-pointer flex items-center justify-center text-gray-300 ml-7 w-10 text-center" @mousedown.prevent @mouseup.prevent @click="$emit('selectPlaybackSpeed')">
<span class="font-mono text-lg">{{ playbackRate }}x</span>
</div>
</template>
<template v-else>
@@ -58,8 +58,9 @@ export default {
data() {
return {
totalDuration: 0,
currentPlaybackRate: 1,
currentTime: 0,
isTerminated: false,
isResetting: false,
initObject: null,
stateName: 'idle',
playInterval: null,
@@ -77,17 +78,24 @@ export default {
computed: {
totalDurationPretty() {
return this.$secondsToTimestamp(this.totalDuration)
},
playbackRate() {
return this.$store.getters['user/getUserSetting']('playbackRate')
}
},
methods: {
updatePlaybackRate() {
this.currentPlaybackRate = this.playbackRate
MyNativeAudio.setPlaybackSpeed({ speed: this.playbackRate })
},
restart() {
this.seek(0)
},
backward10() {
MyNativeAudio.seekBackward10()
MyNativeAudio.seekBackward({ amount: '10000' })
},
forward10() {
MyNativeAudio.seekForward10()
MyNativeAudio.seekForward({ amount: '10000' })
},
sendStreamUpdate() {
this.$emit('updateTime', this.currentTime)
@@ -191,7 +199,9 @@ export default {
}
},
set(audiobookStreamData) {
this.isResetting = false
this.initObject = { ...audiobookStreamData }
this.currentPlaybackRate = this.initObject.playbackSpeed
MyNativeAudio.initPlayer(this.initObject)
},
setFromObj() {
@@ -199,6 +209,7 @@ export default {
console.error('Cannot set from obj')
return
}
this.isResetting = false
MyNativeAudio.initPlayer(this.initObject)
},
play() {
@@ -220,13 +231,17 @@ export default {
stopPlayInterval() {
clearInterval(this.playInterval)
},
terminateStream(startTime) {
resetStream(startTime) {
var _time = String(Math.floor(startTime * 1000))
if (!this.initObject) {
console.error('Terminate stream when no init object is set...')
return
}
this.isResetting = true
this.initObject.currentTime = _time
this.terminateStream()
},
terminateStream() {
MyNativeAudio.terminateStream()
},
init() {
@@ -245,7 +260,7 @@ export default {
this.currentTime = Number((data.currentTime / 1000).toFixed(2))
this.stateName = data.stateName
if (this.stateName === 'ended' && this.isTerminated) {
if (this.stateName === 'ended' && this.isResetting) {
this.setFromObj()
}
+24 -6
View File
@@ -1,15 +1,26 @@
<template>
<div class="w-full h-16 bg-primary relative">
<div id="appbar" class="absolute top-0 left-0 w-full h-full z-30 flex items-center px-2">
<nuxt-link v-show="!showBack" to="/" class="mr-4">
<img src="/Logo.png" class="h-12 w-12" />
<nuxt-link v-show="!showBack" to="/" class="mr-3">
<img src="/Logo.png" class="h-10 w-10" />
</nuxt-link>
<a v-if="showBack" @click="back" class="rounded-full h-12 w-12 flex items-center justify-center hover:bg-white hover:bg-opacity-10 mr-2 cursor-pointer">
<span class="material-icons text-4xl text-white">arrow_back</span>
<a v-if="showBack" @click="back" class="rounded-full h-10 w-10 flex items-center justify-center hover:bg-white hover:bg-opacity-10 mr-2 cursor-pointer">
<span class="material-icons text-3xl text-white">arrow_back</span>
</a>
<p class="text-xl font-book">AudioBookshelf</p>
<div>
<p class="text-lg font-book leading-4">AudioBookshelf</p>
</div>
<div class="flex-grow" />
<ui-menu :label="username" :items="menuItems" @action="menuAction" class="ml-5" />
<!-- <ui-menu :label="username" :items="menuItems" @action="menuAction" class="ml-5" /> -->
<nuxt-link to="/account" class="relative w-28 bg-fg border border-gray-500 rounded shadow-sm ml-5 pl-3 pr-10 py-2 text-left focus:outline-none sm:text-sm cursor-pointer hover:bg-bg hover:bg-opacity-40" aria-haspopup="listbox" aria-expanded="true">
<span class="flex items-center">
<span class="block truncate">{{ username }}</span>
</span>
<span class="ml-3 absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
<span class="material-icons text-gray-100">person</span>
</span>
</nuxt-link>
</div>
</div>
</template>
@@ -40,6 +51,13 @@ export default {
},
username() {
return this.user ? this.user.username : 'err'
},
appListingUrl() {
if (this.$platform === 'android') {
return process.env.ANDROID_APP_URL
} else {
return process.env.IOS_APP_URL
}
}
},
methods: {
+10 -6
View File
@@ -3,16 +3,17 @@
<template v-for="(shelf, index) in groupedBooks">
<div :key="index" class="border-b border-opacity-10 w-full bookshelfRow py-4 flex justify-around relative">
<template v-for="audiobook in shelf">
<div :key="audiobook.id" class="relative px-4">
<nuxt-link :to="`/audiobook/${audiobook.id}`">
<cards-book-cover :audiobook="audiobook" :width="cardWidth" class="mx-auto -mb-px" />
</nuxt-link>
</div>
<!-- <div :key="audiobook.id" class="relative px-4"> -->
<cards-book-card :key="audiobook.id" :audiobook="audiobook" :width="cardWidth" :user-progress="userAudiobooks[audiobook.id]" />
<!-- <nuxt-link :to="`/audiobook/${audiobook.id}`">
<cards-book-cover :audiobook="audiobook" :width="cardWidth" class="mx-auto -mb-px" style="box-shadow: 4px 1px 8px #11111166, -4px 1px 8px #11111166, 1px -4px 8px #11111166" />
</nuxt-link> -->
<!-- </div> -->
</template>
<div class="bookshelfDivider h-4 w-full absolute bottom-0 left-0 right-0 z-10" />
</div>
</template>
<div class="w-full py-16 text-center text-xl">
<div v-show="!groupedBooks.length" class="w-full py-16 text-center text-xl">
<div class="py-4">No Audiobooks</div>
<ui-btn v-if="hasFilters" @click="clearFilter">Clear Filter</ui-btn>
</div>
@@ -40,6 +41,9 @@ export default {
},
hasFilters() {
return this.$store.getters['user/getUserSetting']('filterBy') !== 'all'
},
userAudiobooks() {
return this.$store.state.user.user ? this.$store.state.user.user.audiobooks || {} : {}
}
},
methods: {
+32 -10
View File
@@ -12,8 +12,9 @@
<div class="absolute left-2 -top-10">
<cards-book-cover :audiobook="streamAudiobook" :width="64" />
</div>
<audio-player-mini ref="audioPlayerMini" :loading="!stream || currStreamAudiobookId !== streamAudiobookId" @updateTime="updateTime" @hook:mounted="audioPlayerMounted" />
<audio-player-mini ref="audioPlayerMini" :loading="!stream || currStreamAudiobookId !== streamAudiobookId" @updateTime="updateTime" @selectPlaybackSpeed="showPlaybackSpeedModal = true" @hook:mounted="audioPlayerMounted" />
</div>
<modals-playback-speed-modal v-model="showPlaybackSpeedModal" :playback-speed.sync="playbackSpeed" @change="changePlaybackSpeed" />
</div>
</template>
@@ -25,7 +26,9 @@ export default {
return {
audioPlayerReady: false,
stream: null,
lastServerUpdateSentSeconds: 0
lastServerUpdateSentSeconds: 0,
showPlaybackSpeedModal: false,
playbackSpeed: 1
}
},
computed: {
@@ -85,6 +88,10 @@ export default {
})
if (value) {
this.$server.socket.emit('close_stream')
this.$store.commit('setStreamAudiobook', null)
if (this.$refs.audioPlayerMini) {
this.$refs.audioPlayerMini.terminateStream()
}
}
},
updateTime(currentTime) {
@@ -122,7 +129,7 @@ export default {
streamReset({ streamId, startTime }) {
if (this.$refs.audioPlayerMini) {
if (this.stream && this.stream.id === streamId) {
this.$refs.audioPlayerMini.terminateStream(startTime)
this.$refs.audioPlayerMini.resetStream(startTime)
}
}
},
@@ -133,10 +140,6 @@ export default {
return
}
if (this.stream && this.stream.id !== stream.id) {
console.error('STREAM CHANGED', this.stream.id, stream.id)
}
this.stream = stream
var playlistUrl = stream.clientPlaylistUri
@@ -149,6 +152,7 @@ export default {
author: this.author,
playWhenReady: !!playOnLoad,
startTime: String(Math.floor(currentTime * 1000)),
playbackSpeed: this.playbackSpeed || 1,
cover: this.coverForNative,
duration: String(Math.floor(this.duration * 1000)),
series: this.seriesTxt,
@@ -156,8 +160,6 @@ export default {
token: this.$store.getters['user/getToken']
}
console.log('audiobook stream data', audiobookStreamData.token, JSON.stringify(audiobookStreamData))
this.$refs.audioPlayerMini.set(audiobookStreamData)
},
audioPlayerMounted() {
@@ -177,11 +179,31 @@ export default {
this.$server.socket.on('stream_progress', this.streamProgress)
this.$server.socket.on('stream_ready', this.streamReady)
this.$server.socket.on('stream_reset', this.streamReset)
},
changePlaybackSpeed(speed) {
this.$store.dispatch('user/updateUserSettings', { playbackRate: speed })
},
settingsUpdated(settings) {
if (this.$refs.audioPlayerMini && this.$refs.audioPlayerMini.currentPlaybackRate !== settings.playbackRate) {
this.playbackSpeed = settings.playbackRate
this.$refs.audioPlayerMini.updatePlaybackRate()
}
}
},
mounted() {
console.warn('Stream Container Mounted')
this.playbackSpeed = this.$store.getters['user/getUserSetting']('playbackRate')
this.setListeners()
this.$store.commit('user/addSettingsListener', { id: 'streamContainer', meth: this.settingsUpdated })
},
beforeDestroy() {
this.$server.socket.off('stream_open', this.streamOpen)
this.$server.socket.off('stream_closed', this.streamClosed)
this.$server.socket.off('stream_progress', this.streamProgress)
this.$server.socket.off('stream_ready', this.streamReady)
this.$server.socket.off('stream_reset', this.streamReset)
this.$store.commit('user/removeSettingsListener', 'streamContainer')
}
}
</script>
+116
View File
@@ -0,0 +1,116 @@
<template>
<div class="relative">
<!-- New Book Flag -->
<div v-if="isNew" class="absolute top-4 left-0 w-4 h-10 pr-2 bg-darkgreen box-shadow-xl">
<div class="absolute top-0 left-0 w-full h-full transform -rotate-90 flex items-center justify-center">
<p class="text-center text-sm">New</p>
</div>
<div class="absolute -bottom-4 left-0 triangle-right" />
</div>
<div class="rounded-sm h-full overflow-hidden relative box-shadow-book">
<nuxt-link :to="`/audiobook/${audiobookId}`" class="cursor-pointer">
<div class="w-full relative" :style="{ height: height + 'px' }">
<cards-book-cover :audiobook="audiobook" :author-override="authorFormat" :width="width" />
<div class="absolute bottom-0 left-0 h-1.5 bg-yellow-400 shadow-sm" :style="{ width: width * userProgressPercent + 'px' }"></div>
<div :style="{ height: 1.5 * sizeMultiplier + 'rem', width: 2.5 * sizeMultiplier + 'rem' }" class="bg-error rounded-r-full shadow-md flex items-center justify-end border-r border-b border-red-300">
<span class="material-icons text-red-100 pr-1" :style="{ fontSize: 0.875 * sizeMultiplier + 'rem' }">priority_high</span>
</div>
</div>
</nuxt-link>
</div>
</div>
</template>
<script>
export default {
props: {
audiobook: {
type: Object,
default: () => null
},
userProgress: {
type: Object,
default: () => null
},
width: {
type: Number,
default: 140
}
},
data() {
return {}
},
computed: {
isNew() {
return this.tags.includes('new')
},
tags() {
return this.audiobook.tags || []
},
audiobookId() {
return this.audiobook.id
},
book() {
return this.audiobook.book || {}
},
height() {
return this.width * 1.6
},
sizeMultiplier() {
return this.width / 120
},
paddingX() {
return 16 * this.sizeMultiplier
},
author() {
return this.book.author
},
authorFL() {
return this.book.authorFL || this.author
},
authorLF() {
return this.book.authorLF || this.author
},
authorFormat() {
if (!this.orderBy || !this.orderBy.startsWith('book.author')) return null
return this.orderBy === 'book.authorLF' ? this.authorLF : this.authorFL
},
orderBy() {
return this.$store.getters['user/getUserSetting']('orderBy')
},
userProgressPercent() {
return this.userProgress ? this.userProgress.progress || 0 : 0
},
showError() {
return this.hasMissingParts || this.hasInvalidParts
},
hasMissingParts() {
return this.audiobook.hasMissingParts
},
hasInvalidParts() {
return this.audiobook.hasInvalidParts
},
errorText() {
var txt = ''
if (this.hasMissingParts) {
txt = `${this.hasMissingParts} missing parts.`
}
if (this.hasInvalidParts) {
if (this.hasMissingParts) txt += ' '
txt += `${this.hasInvalidParts} invalid parts.`
}
return txt || 'Unknown Error'
}
},
methods: {
play() {
this.$store.commit('setStreamAudiobook', this.audiobook)
this.$root.socket.emit('open_stream', this.audiobookId)
}
},
mounted() {}
}
</script>
+1 -1
View File
@@ -9,7 +9,7 @@
<div v-if="imageFailed" class="absolute top-0 left-0 right-0 bottom-0 w-full h-full bg-red-100" :style="{ padding: placeholderCoverPadding + 'rem' }">
<div class="w-full h-full border-2 border-error flex flex-col items-center justify-center">
<img src="/LogoTransparent.png" class="mb-2" :style="{ height: 64 * sizeMultiplier + 'px' }" />
<img src="/Logo.png" class="mb-2" :style="{ height: 64 * sizeMultiplier + 'px' }" />
<p class="text-center font-book text-error" :style="{ fontSize: titleFontSize + 'rem' }">Invalid Cover</p>
</div>
</div>
+1 -1
View File
@@ -6,7 +6,7 @@
<span class="material-icons text-4xl">close</span>
</div>
<slot name="outer" />
<div ref="content" style="min-width: 90%; min-height: 200px" class="relative text-white max-h-screen" :style="{ height: modalHeight, width: modalWidth }" v-click-outside="clickBg">
<div ref="content" style="max-width: 90%; min-height: 200px" class="relative text-white max-h-screen" :style="{ height: modalHeight, width: modalWidth }" v-click-outside="clickBg">
<slot />
</div>
</div>
+62
View File
@@ -0,0 +1,62 @@
<template>
<modals-modal v-model="show" :width="200" height="100%">
<div class="w-full h-full overflow-hidden absolute top-0 left-0 flex items-center justify-center" @click="show = false">
<div class="w-full overflow-x-hidden overflow-y-auto bg-primary rounded-lg border border-white border-opacity-20" style="max-height: 75%" @click.stop>
<ul class="h-full w-full" role="listbox" aria-labelledby="listbox-label">
<template v-for="rate in rates">
<li :key="rate" class="text-gray-50 select-none relative py-4 pr-9 cursor-pointer hover:bg-black-400" :class="rate === selected ? 'bg-bg bg-opacity-50' : ''" role="option" @click="clickedOption(rate)">
<div class="flex items-center justify-center">
<span class="font-normal ml-3 block truncate text-lg">{{ rate }}x</span>
</div>
</li>
</template>
</ul>
</div>
</div>
</modals-modal>
</template>
<script>
export default {
props: {
value: Boolean,
playbackSpeed: Number
},
data() {
return {}
},
computed: {
show: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
},
selected: {
get() {
return this.playbackSpeed
},
set(val) {
this.$emit('update:playbackSpeed', val)
}
},
rates() {
return [0.25, 0.5, 0.8, 1, 1.3, 1.5, 2, 2.5, 3]
}
},
methods: {
clickedOption(speed) {
if (this.selected === speed) {
this.show = false
return
}
this.selected = speed
this.show = false
this.$nextTick(() => this.$emit('change', speed))
}
},
mounted() {}
}
</script>
+3 -2
View File
@@ -1,5 +1,5 @@
<template>
<button class="btn outline-none rounded-md shadow-md relative border border-gray-600" :disabled="loading" :type="type" :class="classList" @click="click">
<button class="btn outline-none rounded-md shadow-md relative border border-gray-600" :disabled="disabled || loading" :type="type" :class="classList" @click="click">
<slot />
<div v-if="loading" class="text-white absolute top-0 left-0 w-full h-full flex items-center justify-center text-opacity-100">
<!-- <span class="material-icons animate-spin">refresh</span> -->
@@ -23,7 +23,8 @@ export default {
},
paddingX: Number,
small: Boolean,
loading: Boolean
loading: Boolean,
disabled: Boolean
},
data() {
return {}
+1 -1
View File
@@ -1,5 +1,5 @@
<template>
<input v-model="input" :type="type" :disabled="disabled" :placeholder="placeholder" class="px-2 py-1 bg-bg border border-gray-600 outline-none rounded-sm" :class="disabled ? 'text-gray-300' : 'text-white'" />
<input v-model="input" :type="type" :disabled="disabled" autocorrect="off" autocapitalize="none" autocomplete="off" :placeholder="placeholder" class="px-2 py-1 bg-bg border border-gray-600 outline-none rounded-sm" :class="disabled ? 'text-gray-300' : 'text-white'" />
</template>
<script>
+9
View File
@@ -0,0 +1,9 @@
App/build
App/Pods
App/Podfile.lock
App/App/public
DerivedData
xcuserdata
# Cordova plugins for Capacitor
capacitor-cordova-ios-plugins
+417
View File
@@ -0,0 +1,417 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 48;
objects = {
/* Begin PBXBuildFile section */
2FAD9763203C412B000D30F8 /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2FAD9762203C412B000D30F8 /* config.xml */; };
4D8D410C26E17C3A00BA5F0D /* MyNativeAudio.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D8D410B26E17C3A00BA5F0D /* MyNativeAudio.swift */; };
4D8D412E26E187E500BA5F0D /* MyNativeAudio.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D8D412D26E187E500BA5F0D /* MyNativeAudio.m */; };
50379B232058CBB4000EE86E /* capacitor.config.json in Resources */ = {isa = PBXBuildFile; fileRef = 50379B222058CBB4000EE86E /* capacitor.config.json */; };
504EC3081FED79650016851F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504EC3071FED79650016851F /* AppDelegate.swift */; };
504EC30D1FED79650016851F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30B1FED79650016851F /* Main.storyboard */; };
504EC30F1FED79650016851F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30E1FED79650016851F /* Assets.xcassets */; };
504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC3101FED79650016851F /* LaunchScreen.storyboard */; };
50B271D11FEDC1A000F3C39B /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; };
A084ECDBA7D38E1E42DFC39D /* Pods_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
2FAD9762203C412B000D30F8 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = config.xml; sourceTree = "<group>"; };
4D8D410B26E17C3A00BA5F0D /* MyNativeAudio.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyNativeAudio.swift; sourceTree = "<group>"; };
4D8D412C26E187E400BA5F0D /* App-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "App-Bridging-Header.h"; sourceTree = "<group>"; };
4D8D412D26E187E500BA5F0D /* MyNativeAudio.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyNativeAudio.m; sourceTree = "<group>"; };
50379B222058CBB4000EE86E /* capacitor.config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = capacitor.config.json; sourceTree = "<group>"; };
504EC3041FED79650016851F /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; };
504EC3071FED79650016851F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
504EC30C1FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
504EC30E1FED79650016851F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
504EC3131FED79650016851F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
50B271D01FEDC1A000F3C39B /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = "<group>"; };
AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App.framework; sourceTree = BUILT_PRODUCTS_DIR; };
AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = "<group>"; };
FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.debug.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
504EC3011FED79650016851F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
A084ECDBA7D38E1E42DFC39D /* Pods_App.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
27E2DDA53C4D2A4D1A88CE4A /* Frameworks */ = {
isa = PBXGroup;
children = (
AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
504EC2FB1FED79650016851F = {
isa = PBXGroup;
children = (
504EC3061FED79650016851F /* App */,
504EC3051FED79650016851F /* Products */,
7F8756D8B27F46E3366F6CEA /* Pods */,
27E2DDA53C4D2A4D1A88CE4A /* Frameworks */,
);
sourceTree = "<group>";
};
504EC3051FED79650016851F /* Products */ = {
isa = PBXGroup;
children = (
504EC3041FED79650016851F /* App.app */,
);
name = Products;
sourceTree = "<group>";
};
504EC3061FED79650016851F /* App */ = {
isa = PBXGroup;
children = (
50379B222058CBB4000EE86E /* capacitor.config.json */,
504EC3071FED79650016851F /* AppDelegate.swift */,
504EC30B1FED79650016851F /* Main.storyboard */,
504EC30E1FED79650016851F /* Assets.xcassets */,
504EC3101FED79650016851F /* LaunchScreen.storyboard */,
504EC3131FED79650016851F /* Info.plist */,
2FAD9762203C412B000D30F8 /* config.xml */,
50B271D01FEDC1A000F3C39B /* public */,
4D8D410B26E17C3A00BA5F0D /* MyNativeAudio.swift */,
4D8D412D26E187E500BA5F0D /* MyNativeAudio.m */,
4D8D412C26E187E400BA5F0D /* App-Bridging-Header.h */,
);
path = App;
sourceTree = "<group>";
};
7F8756D8B27F46E3366F6CEA /* Pods */ = {
isa = PBXGroup;
children = (
FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */,
AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
504EC3031FED79650016851F /* App */ = {
isa = PBXNativeTarget;
buildConfigurationList = 504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "App" */;
buildPhases = (
6634F4EFEBD30273BCE97C65 /* [CP] Check Pods Manifest.lock */,
504EC3001FED79650016851F /* Sources */,
504EC3011FED79650016851F /* Frameworks */,
504EC3021FED79650016851F /* Resources */,
9592DBEFFC6D2A0C8D5DEB22 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = App;
productName = App;
productReference = 504EC3041FED79650016851F /* App.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
504EC2FC1FED79650016851F /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0920;
LastUpgradeCheck = 0920;
TargetAttributes = {
504EC3031FED79650016851F = {
CreatedOnToolsVersion = 9.2;
LastSwiftMigration = 1240;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = 504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */;
compatibilityVersion = "Xcode 8.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 504EC2FB1FED79650016851F;
productRefGroup = 504EC3051FED79650016851F /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
504EC3031FED79650016851F /* App */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
504EC3021FED79650016851F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */,
50B271D11FEDC1A000F3C39B /* public in Resources */,
504EC30F1FED79650016851F /* Assets.xcassets in Resources */,
50379B232058CBB4000EE86E /* capacitor.config.json in Resources */,
504EC30D1FED79650016851F /* Main.storyboard in Resources */,
2FAD9763203C412B000D30F8 /* config.xml in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
6634F4EFEBD30273BCE97C65 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-App-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
9592DBEFFC6D2A0C8D5DEB22 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-App/Pods-App-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
504EC3001FED79650016851F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4D8D412E26E187E500BA5F0D /* MyNativeAudio.m in Sources */,
504EC3081FED79650016851F /* AppDelegate.swift in Sources */,
4D8D410C26E17C3A00BA5F0D /* MyNativeAudio.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
504EC30B1FED79650016851F /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
504EC30C1FED79650016851F /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
504EC3101FED79650016851F /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
504EC3111FED79650016851F /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
504EC3141FED79650016851F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
504EC3151FED79650016851F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
504EC3171FED79650016851F /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
PRODUCT_BUNDLE_IDENTIFIER = com.audiobookshelf.app;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OBJC_BRIDGING_HEADER = "App/App-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
504EC3181FED79650016851F /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.audiobookshelf.app;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
SWIFT_OBJC_BRIDGING_HEADER = "App/App-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */ = {
isa = XCConfigurationList;
buildConfigurations = (
504EC3141FED79650016851F /* Debug */,
504EC3151FED79650016851F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "App" */ = {
isa = XCConfigurationList;
buildConfigurations = (
504EC3171FED79650016851F /* Debug */,
504EC3181FED79650016851F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 504EC2FC1FED79650016851F /* Project object */;
}
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:App.xcodeproj">
</FileRef>
</Workspace>
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:App.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
+4
View File
@@ -0,0 +1,4 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
+60
View File
@@ -0,0 +1,60 @@
import UIKit
import Capacitor
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
// Called when the app was launched with a url. Feel free to add additional processing here,
// but if you want the App API to support tracking app url opens, make sure to keep this call
return ApplicationDelegateProxy.shared.application(app, open: url, options: options)
}
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
// Called when the app was launched with an activity, including Universal Links.
// Feel free to add additional processing here, but if you want the App API to support
// tracking app url opens, make sure to keep this call
return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
let statusBarRect = UIApplication.shared.statusBarFrame
guard let touchPoint = event?.allTouches?.first?.location(in: self.window) else { return }
if statusBarRect.contains(touchPoint) {
NotificationCenter.default.post(name: .capacitorStatusBarTapped, object: nil)
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 774 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Some files were not shown because too many files have changed in this diff Show More