Compare commits
7 Commits
feature/re
...
v1.2.6-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f39ab85624 | ||
|
|
01bd17e8cb | ||
|
|
1075e31623 | ||
|
|
8678e3d881 | ||
|
|
0fc087e832 | ||
|
|
a8d563f66d | ||
|
|
1c659d7d90 |
10
README.md
@@ -7,8 +7,10 @@ This is a [React Native](https://reactnative.dev/)-based audio streaming app for
|
||||
## ❗️Now open for beta testing on iOS
|
||||
Please follow this link to enroll for the TestFlight beta release of Jellyfin Audio Player: https://testflight.apple.com/join/cf2AMDpx.
|
||||
|
||||
|||||
|
||||
|-|-|-|-|
|
||||
|||
|
||||
|-|-|-|
|
||||
|||
|
||||
|
||||
|
||||
## Features
|
||||
* Sorting by recent albums
|
||||
@@ -18,14 +20,12 @@ Please follow this link to enroll for the TestFlight beta release of Jellyfin Au
|
||||
* AirPlay and Chromecast support
|
||||
* Background audio
|
||||
* Native Dark Mode
|
||||
|
||||
### Features being considered
|
||||
* Downloading music for offline playback
|
||||
* Searching based on track names
|
||||
* Looping and shuffling queue
|
||||
|
||||
## Getting Started
|
||||
This piece of software is in alpha. I am working on getting this app in ~~TestFlight and~~ Google Play Developer Console, but this is contingent on keys being available. In the meantime, IPAs and APK are intermittenly released on the [Releases page](https://github.com/leinelissen/jellyfin-audio-player/releases). Alternatively, you can build this app from source using the build instructions.
|
||||
This piece of software is in beta. I am working on getting this app in ~~TestFlight and~~ Google Play Developer Console, but this is contingent on keys being available. In the meantime, IPAs and APK are intermittenly released on the [Releases page](https://github.com/leinelissen/jellyfin-audio-player/releases). Alternatively, you can build this app from source using the build instructions.
|
||||
|
||||
### Using the app
|
||||
You will need to setup your Jellyfin account for the application to be able to pull in all your audio. To do this, go over to the "Settings" tab and click the "Set Jellyfin server"-button. A modal will pop up in which you will enter your Jellyfin server url, after which you enter your credentials in the provided browser view. When the app detects your credentials, they will automatically be remembered for the future.
|
||||
|
||||
@@ -138,8 +138,8 @@ android {
|
||||
applicationId "com.jellyfinaudioplayer"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 8
|
||||
versionName "1.2.4"
|
||||
versionCode 9
|
||||
versionName "1.2.5"
|
||||
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
||||
|
||||
if (isNewArchitectureEnabled()) {
|
||||
@@ -322,4 +322,4 @@ def isNewArchitectureEnabled() {
|
||||
// - Invoke gradle with `-newArchEnabled=true`
|
||||
// - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true`
|
||||
return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 222 KiB After Width: | Height: | Size: 2.9 MiB |
BIN
docs/images/album.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
docs/images/downloads.png
Normal file
|
After Width: | Height: | Size: 506 KiB |
|
Before Width: | Height: | Size: 252 KiB After Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 282 KiB After Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 261 KiB |
@@ -555,7 +555,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 36;
|
||||
CURRENT_PROJECT_VERSION = 37;
|
||||
DEVELOPMENT_TEAM = 238P3C58WC;
|
||||
ENABLE_BITCODE = NO;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
@@ -591,7 +591,7 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 36;
|
||||
CURRENT_PROJECT_VERSION = 37;
|
||||
DEVELOPMENT_TEAM = 238P3C58WC;
|
||||
INFOPLIST_FILE = JellyfinAudioPlayer/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.2.4</string>
|
||||
<string>1.2.5</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>36</string>
|
||||
<string>37</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.2.4</string>
|
||||
<string>1.2.5</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>36</string>
|
||||
<string>37</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
18
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "JellyfinAudioPlayer",
|
||||
"version": "1.2.4",
|
||||
"version": "1.2.5",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "JellyfinAudioPlayer",
|
||||
"version": "1.2.4",
|
||||
"version": "1.2.5",
|
||||
"dependencies": {
|
||||
"@react-native-community/async-storage": "^1.12.1",
|
||||
"@react-native-community/blur": "^3.6.0",
|
||||
@@ -45,7 +45,7 @@
|
||||
"react-native-shadow-2": "^6.0.5",
|
||||
"react-native-svg": "^12.3.0",
|
||||
"react-native-svg-transformer": "^1.0.0",
|
||||
"react-native-track-player": "^2.1.3",
|
||||
"react-native-track-player": "^2.2.0-rc3",
|
||||
"react-native-webview": "^11.18.2",
|
||||
"react-redux": "^8.0.1",
|
||||
"redux": "^4.2.0",
|
||||
@@ -14268,9 +14268,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-track-player": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/react-native-track-player/-/react-native-track-player-2.1.3.tgz",
|
||||
"integrity": "sha512-JWKFRu+hr1ECN339RH+c+XDM7HfwvdvS4H1p4cJbhg/9b1CQGPJSrYXEhYkngN0msoxBxAjFyFIhjT2fWDCltA==",
|
||||
"version": "2.2.0-rc3",
|
||||
"resolved": "https://registry.npmjs.org/react-native-track-player/-/react-native-track-player-2.2.0-rc3.tgz",
|
||||
"integrity": "sha512-Pvmum3MQ5PE8/yOIIPsk00zZk3EzdocUuVUwuBKSCmdKK/3O9YhnZRC3EuT59XCDm23pZZJZDSR44VeXN6Gamg==",
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.6",
|
||||
"react-native": ">=0.60.0-rc.2",
|
||||
@@ -28569,9 +28569,9 @@
|
||||
}
|
||||
},
|
||||
"react-native-track-player": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/react-native-track-player/-/react-native-track-player-2.1.3.tgz",
|
||||
"integrity": "sha512-JWKFRu+hr1ECN339RH+c+XDM7HfwvdvS4H1p4cJbhg/9b1CQGPJSrYXEhYkngN0msoxBxAjFyFIhjT2fWDCltA==",
|
||||
"version": "2.2.0-rc3",
|
||||
"resolved": "https://registry.npmjs.org/react-native-track-player/-/react-native-track-player-2.2.0-rc3.tgz",
|
||||
"integrity": "sha512-Pvmum3MQ5PE8/yOIIPsk00zZk3EzdocUuVUwuBKSCmdKK/3O9YhnZRC3EuT59XCDm23pZZJZDSR44VeXN6Gamg==",
|
||||
"requires": {}
|
||||
},
|
||||
"react-native-webview": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "JellyfinAudioPlayer",
|
||||
"version": "1.2.4",
|
||||
"version": "1.2.5",
|
||||
"main": "src/index.js",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@@ -49,7 +49,7 @@
|
||||
"react-native-shadow-2": "^6.0.5",
|
||||
"react-native-svg": "^12.3.0",
|
||||
"react-native-svg-transformer": "^1.0.0",
|
||||
"react-native-track-player": "^2.1.3",
|
||||
"react-native-track-player": "^2.2.0-rc3",
|
||||
"react-native-webview": "^11.18.2",
|
||||
"react-redux": "^8.0.1",
|
||||
"redux": "^4.2.0",
|
||||
|
||||
3
src/assets/icons/xmark.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.18849 19.0509C6.81935 19.4201 6.80177 20.0792 7.19728 20.466C7.58399 20.8527 8.24317 20.8439 8.61231 20.4747L13.9912 15.087L19.3789 20.4747C19.7568 20.8527 20.4072 20.8527 20.794 20.466C21.1719 20.0704 21.1807 19.4288 20.794 19.0509L15.415 13.6632L20.794 8.28431C21.1807 7.90638 21.1807 7.25599 20.794 6.86927C20.3984 6.49134 19.7568 6.48255 19.3789 6.86048L13.9912 12.2482L8.61231 6.86048C8.24317 6.49134 7.5752 6.47376 7.19728 6.86927C6.81056 7.25599 6.81935 7.91517 7.18849 8.28431L12.5762 13.6632L7.18849 19.0509Z" fill="#1C1C1E"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 651 B |
@@ -2,7 +2,7 @@ import { BlurView, BlurViewProperties } from '@react-native-community/blur';
|
||||
import { THEME_COLOR } from 'CONSTANTS';
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
import { useContext } from 'react';
|
||||
import { ColorSchemeName, Platform, StyleSheet, useColorScheme } from 'react-native';
|
||||
import { ColorSchemeName, Platform, StyleSheet, useColorScheme, View } from 'react-native';
|
||||
|
||||
const majorPlatformVersion = typeof Platform.Version === 'string' ? parseInt(Platform.Version, 10) : Platform.Version;
|
||||
|
||||
@@ -100,12 +100,16 @@ export function DefaultStylesProvider(props: DefaultStylesProviderProps) {
|
||||
export function ColoredBlurView(props: PropsWithChildren<BlurViewProperties>) {
|
||||
const scheme = useColorScheme();
|
||||
|
||||
return (
|
||||
return Platform.OS === 'ios' ? (
|
||||
<BlurView
|
||||
{...props}
|
||||
blurType={Platform.OS === 'ios' && majorPlatformVersion >= 13
|
||||
? 'material'
|
||||
: scheme === 'dark' ? 'extraDark' : 'xlight'
|
||||
} />
|
||||
) : (
|
||||
<View {...props} style={[ props.style, {
|
||||
backgroundColor: scheme === 'light' ? '#f6f6f6f6' : '#333333f6',
|
||||
} ]} />
|
||||
);
|
||||
}
|
||||
@@ -32,7 +32,8 @@ const Logo = styled.Image`
|
||||
height: 150px;
|
||||
margin: 0 auto 50px auto;
|
||||
border-radius: 12px;
|
||||
border: 1px solid #e6e6e6;
|
||||
border-width: 1px;
|
||||
border-color: #e6e6e6;
|
||||
`;
|
||||
|
||||
function Onboarding() {
|
||||
|
||||
28
src/screens/modals/Player/components/Backbutton.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import XmarkIcon from 'assets/icons/xmark.svg';
|
||||
import { TouchableOpacity } from 'react-native';
|
||||
import styled from 'styled-components/native';
|
||||
|
||||
const Container = styled.View`
|
||||
padding: 6px 12px;
|
||||
`;
|
||||
|
||||
function BackButton() {
|
||||
const navigation = useNavigation();
|
||||
|
||||
const handlePress = useCallback(() => {
|
||||
console.log(navigation.canGoBack());
|
||||
navigation.goBack();
|
||||
}, [navigation]);
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<TouchableOpacity onPress={handlePress}>
|
||||
<XmarkIcon />
|
||||
</TouchableOpacity>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
export default BackButton;
|
||||
@@ -1,16 +1,14 @@
|
||||
import { t } from '@localisation';
|
||||
import React from 'react';
|
||||
import { Text } from 'react-native';
|
||||
import styled from 'styled-components/native';
|
||||
|
||||
const Button = styled.View`
|
||||
margin: 20px 40px;
|
||||
const Label = styled.Text`
|
||||
font-size: 13px;
|
||||
`;
|
||||
|
||||
function Casting() {
|
||||
return (
|
||||
<Button>
|
||||
<Text>Local Playback</Text>
|
||||
</Button>
|
||||
<Label>{t('local-playback')}</Label>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import ticksToDuration from 'utility/ticksToDuration';
|
||||
const ICON_SIZE = 16;
|
||||
|
||||
const Container = styled.FlatList<Track>`
|
||||
padding: 40px;
|
||||
|
||||
`;
|
||||
|
||||
const Header = styled.View`
|
||||
@@ -103,6 +103,7 @@ export default function Queue({ header }: Props) {
|
||||
|
||||
return (
|
||||
<Container
|
||||
contentContainerStyle={{ padding: 40 }}
|
||||
data={queue}
|
||||
ListHeaderComponent={
|
||||
<>
|
||||
|
||||
@@ -6,10 +6,13 @@ import Queue from './components/Queue';
|
||||
import ConnectionNotice from './components/ConnectionNotice';
|
||||
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
||||
import StreamStatus from './components/StreamStatus';
|
||||
import { Platform } from 'react-native';
|
||||
import BackButton from './components/Backbutton';
|
||||
|
||||
export default function Player() {
|
||||
return (
|
||||
<GestureHandlerRootView style={{ flex: 1 }}>
|
||||
{Platform.OS === 'android' && (<BackButton />)}
|
||||
<Queue header={(
|
||||
<>
|
||||
<NowPlaying />
|
||||
|
||||