diff --git a/index.ts b/index.ts index f725a6a..f16aef1 100644 --- a/index.ts +++ b/index.ts @@ -1,6 +1,9 @@ import 'react-native-gesture-handler'; import { AppRegistry } from 'react-native'; +import TrackPlayer from 'react-native-track-player'; import App from './src/components/App'; import { name as appName } from './app.json'; +import PlaybackService from './src/utility/PlaybackService'; AppRegistry.registerComponent(appName, () => App); +TrackPlayer.registerPlaybackService(() => PlaybackService); \ No newline at end of file diff --git a/ios/JellyfinAudioPlayer.xcodeproj/project.pbxproj b/ios/JellyfinAudioPlayer.xcodeproj/project.pbxproj index 3c739d6..382b280 100644 --- a/ios/JellyfinAudioPlayer.xcodeproj/project.pbxproj +++ b/ios/JellyfinAudioPlayer.xcodeproj/project.pbxproj @@ -288,17 +288,21 @@ TargetAttributes = { 00E356ED1AD99517003FC87E = { CreatedOnToolsVersion = 6.2; + DevelopmentTeam = HD2D35G9Y4; TestTargetID = 13B07F861A680F5B00A75B9A; }; 13B07F861A680F5B00A75B9A = { + DevelopmentTeam = HD2D35G9Y4; LastSwiftMigration = 1120; }; 2D02E47A1E0B4A5D006451C7 = { CreatedOnToolsVersion = 8.2.1; + DevelopmentTeam = HD2D35G9Y4; ProvisioningStyle = Automatic; }; 2D02E48F1E0B4A5D006451C7 = { CreatedOnToolsVersion = 8.2.1; + DevelopmentTeam = HD2D35G9Y4; ProvisioningStyle = Automatic; TestTargetID = 2D02E47A1E0B4A5D006451C7; }; @@ -584,6 +588,7 @@ baseConfigurationReference = 8DAD3DCD6450C4255A20940E /* Pods-JellyfinAudioPlayer-JellyfinAudioPlayerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; + DEVELOPMENT_TEAM = HD2D35G9Y4; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", @@ -608,6 +613,7 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = HD2D35G9Y4; INFOPLIST_FILE = JellyfinAudioPlayerTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -629,6 +635,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = HD2D35G9Y4; ENABLE_BITCODE = NO; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", @@ -656,6 +663,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = HD2D35G9Y4; INFOPLIST_FILE = JellyfinAudioPlayer/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = ( @@ -681,6 +689,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = HD2D35G9Y4; ENABLE_TESTABILITY = YES; GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = "JellyfinAudioPlayer-tvOS/Info.plist"; @@ -710,6 +719,7 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = HD2D35G9Y4; GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = "JellyfinAudioPlayer-tvOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -736,6 +746,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = HD2D35G9Y4; ENABLE_TESTABILITY = YES; GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = "JellyfinAudioPlayer-tvOSTests/Info.plist"; @@ -764,6 +775,7 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = HD2D35G9Y4; GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = "JellyfinAudioPlayer-tvOSTests/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; diff --git a/ios/JellyfinAudioPlayer/Info.plist b/ios/JellyfinAudioPlayer/Info.plist index 1a546c2..c385a06 100644 --- a/ios/JellyfinAudioPlayer/Info.plist +++ b/ios/JellyfinAudioPlayer/Info.plist @@ -42,6 +42,7 @@ UIBackgroundModes audio + processing UILaunchStoryboardName LaunchScreen diff --git a/src/components/App.tsx b/src/components/App.tsx index caf853e..f336983 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -14,6 +14,15 @@ export default class App extends Component { async componentDidMount() { await TrackPlayer.setupPlayer(); + await TrackPlayer.updateOptions({ + capabilities: [ + TrackPlayer.CAPABILITY_PLAY, + TrackPlayer.CAPABILITY_PAUSE, + TrackPlayer.CAPABILITY_SKIP_TO_NEXT, + TrackPlayer.CAPABILITY_SKIP_TO_PREVIOUS, + TrackPlayer.CAPABILITY_STOP, + ] + }); this.setState({ isReady: true }); } diff --git a/src/screens/Player/components/MediaControls.tsx b/src/screens/Player/components/MediaControls.tsx index 1b879ba..ac2ef42 100644 --- a/src/screens/Player/components/MediaControls.tsx +++ b/src/screens/Player/components/MediaControls.tsx @@ -23,10 +23,12 @@ const Container = styled.View` const Buttons = styled.View` flex-direction: row; align-items: center; + justify-content: space-between; + width: 100%; `; const Button = styled.View` - margin: 20px; + margin: 20px 40px; `; export default function MediaControls() { diff --git a/src/screens/Player/components/NowPlaying.tsx b/src/screens/Player/components/NowPlaying.tsx index 8dd819b..2fb1d50 100644 --- a/src/screens/Player/components/NowPlaying.tsx +++ b/src/screens/Player/components/NowPlaying.tsx @@ -18,16 +18,11 @@ const Artwork = styled.Image` export default function NowPlaying() { const track = useCurrentTrack(); - // GUARD: Don't render anything if nothing is playing - if (!track) { - return null; - } - return ( - - {track.artist} - {track.title} + + {track?.artist} + {track?.title} ); } \ No newline at end of file diff --git a/src/utility/PlaybackService.ts b/src/utility/PlaybackService.ts new file mode 100644 index 0000000..848af26 --- /dev/null +++ b/src/utility/PlaybackService.ts @@ -0,0 +1,32 @@ +/** +* This is the code that will run tied to the player. +* +* The code here might keep running in the background. +* +* You should put everything here that should be tied to the playback but not the UI +* such as processing media buttons or analytics +*/ + +import TrackPlayer from 'react-native-track-player'; + +export default async function() { + TrackPlayer.addEventListener('remote-play', () => { + TrackPlayer.play(); + }); + + TrackPlayer.addEventListener('remote-pause', () => { + TrackPlayer.pause(); + }); + + TrackPlayer.addEventListener('remote-next', () => { + TrackPlayer.skipToNext(); + }); + + TrackPlayer.addEventListener('remote-previous', () => { + TrackPlayer.skipToPrevious(); + }); + + TrackPlayer.addEventListener('remote-stop', () => { + TrackPlayer.destroy(); + }); +} \ No newline at end of file