Repo created

This commit is contained in:
Fr4nz D13trich 2025-11-24 08:22:15 +01:00
parent 5b950caea0
commit 477d1afe74
805 changed files with 316919 additions and 2 deletions

View file

@ -0,0 +1,42 @@
@startuml
(*) --> "OnResume"
"OnResume" --> "Register Player Observer"
"OnResume" --> "Register Playlist Observer"
"Register Playlist Observer" --> ===A1===
===A1=== --> "playlistsAvailable"
"playlistsAvailable" --> "Store playlists"
"Store playlists" --> "Set tab icons to playlist available"
"Set tab icons to playlist available" --> "Check player state"
"Check player state" --> ===A2===
===A2=== --> "Stopped after playing"
--> "Update playlist"
===A2=== --> "Nothing played yet"
--> if "User selected tab?"
--> [No] "Switch to first available playlist"
else
--> [Yes] "Update playlist"
endif
===A2=== --> "Paused"
--> "Update playlist"
===A2=== --> "Playing"
--> "Do nothing"
===A1=== --> "playlistOnClear"
"playlistOnClear" --> "Remove playlist"
"Remove playlist" --> "Show empty playlist message"
"Register Player Observer" --> ===B1===
===B1=== --> "playerOnConnectionError"
===B1=== --> "playerOnPause"
===B1=== --> "playerOnPlay"
===B1=== --> "playerOnStop"
"playerOnStop" --> "Keep showing current playlist"
"Keep showing current playlist" --> "Set tab icon to NOT playing"
"playerOnConnectionError" --> "Clear local playlists"
"Clear local playlists" --> "Show error message"
"Show error message" --> "Set tab icons to no_playlist state"
"playerOnPause" --> ===B2===
"playerOnPlay" --> ===B2===
===B2=== --> "Set tab icon to playing"
--> if "User did not select a tab?"
--> [Yes] "Switch to tab for given playlist"
endif
@enduml

View file

@ -0,0 +1,180 @@
@startuml
interface SharedElement {
Required for all fragments that
support shared element transitions
+ boolean isSharedElementVisible()
}
class DataHolder {
Holds required data used by info and details fragments
+ DataHolder(Bundle bundle)
+ DataHolder(int itemId)
+ void setBundle(Bundle bundle)
+ void setPosterTransitionName(String posterTransitionName)
+ void setSquarePoster(boolean squarePoster)
+ void setRating(double rating)
+ void setMaxRating(int maxRating)
+ void setVotes(int votes)
+ void setPosterUrl(String posterUrl)
+ void setTitle(String title)
+ void setUndertitle(String underTitle)
+ void setDescription(String description)
+ void setDetails(String details)
+ void setFanArtUrl(String fanArtUrl)
+ void setId(int id)
+ String getPosterTransitionName()
+ boolean getSquarePoster()
+ double getRating()
+ int getMaxRating()
+ int getVotes()
+ String getPosterUrl()
+ String getTitle()
+ String getUnderTitle()
+ String getDescription()
+ String getDetails()
+ String getFanArtUrl()
+ int getId()
+ Bundle getBundle()
}
abstract class AbstractFragment {
Holds the dataholder to provide quick access to required data in info
and detail fragments. This is required to provide a smooth and
responsive UX, especially when using shared element transitions.
+ void setDataHolder(AbstractInfoFragment.DataHolder dataHolder)
+ AbstractInfoFragment.DataHolder getDataHolder()
}
abstract class AbstractAdditionalInfoFragment {
Defines mandatory methods for fragments that can be added to
information fragments
+ abstract void refresh()
}
abstract class AbstractInfoFragment {
Defines a common UI for information fragments. Concrete implementations
of this class should ideally only provide the data, while the
AbstractInfoFragment contains the logic to present the UI and react to
user input.
-- Implements --
+ boolean isSharedElementVisible()
-- Generic --
Allows concrete fragment to get certain data or update the UI
--
# void refreshAdditionInfoFragment()
# HostManager getHostManager()
# HostInfo getHostInfo()
# void updateView(DataHolder dataHolder)
# RefreshItem getRefreshItem()
# void setExpandDescription(boolean expandDescription)
-- Media action bar --
Adding a listener in a concrete fragment will add the corresponding
button to the UI
--
# void setOnDownloadListener(final View.OnClickListener listener)
# void setOnAddToPlaylistListener(View.OnClickListener listener)
# void setOnGoToImdbListener(View.OnClickListener listener)
# void setOnSeenListener(final View.OnClickListener listener)
# void setOnPinClickedListener(final View.OnClickListener listener)
# void setDownloadButtonState(boolean state)
# void setSeenButtonState(boolean state)
# void setPinButtonState(boolean state)
-- Abstract methods --
Every concrete fragment is able to add additional info using an
AbstractAdditionalInfoFragment. This will be placed below the generic info.
Every concrete fragment should implement a refresh functionality.
The method setupMediaActionBar() will be called when the media action bar buttons
are available. This is where the concrete fragment should call the setOn*Listeners
to connect listeners to specific media action buttons.
The method setupFAB(ImageButton FAB) will be called to allow adding a listener.
It should return true to enable the FAB, false to disabled it.
--
# {abstract} AbstractAdditionalInfoFragment getAdditionalInfoFragment()
# {abstract} RefreshItem createRefreshItem()
# {abstract} boolean setupMediaActionBar()
# {abstract} boolean setupFAB(ImageButton FAB)
}
abstract class AbstractTabsFragment {
Defines a common UI for fragments that want to use a viewpager and a scrollable tab bar.
-- Implements --
+ boolean isSharedElementVisible()
--
# {abstract} TabsAdapter createTabsAdapter(AbstractInfoFragment.DataHolder dataHolder)
}
class ConcreteTabsFragment {
The returned TabsAdapter should hold all required tabs
# TabsAdapter createTabsAdapter(AbstractInfoFragment.DataHolder dataHolder)
}
class ConcreteInfoFragment {
Should be able to provide the required information by updating the DataHolder.
Use getDataHolder() to get the current DataHolder and update it. Use updateView(DataHolder)
to force an update of the UI with the updated DataHolder.
--
# AbstractAdditionalInfoFragment getAdditionalInfoFragment()
# RefreshItem createRefreshItem()
# boolean setupMediaActionBar()
}
class ConcreteAdditionalInfoFragment {
# void refresh()
}
abstract class AbstractListFragment {
# {abstract} AdapterView.OnItemClickListener createOnItemClickListener()
# {abstract} BaseAdapter createAdapter()
+ void hideRefreshAnimation()
+ void showRefreshAnimation()
+ BaseAdapter getAdapter()
+ TextView getEmptyView()
}
abstract class AbstractCursorListFragment {
# {abstract} void onListItemClicked(View view)
# {abstract} CursorLoader createCursorLoader()
# {abstract} String getListSyncType()
# AdapterView.OnItemClickListener createOnItemClickListener()
# String getSyncID()
# int getSyncItemID()
# void onRefresh()
+ void refreshList()
+ String getSearchFilter()
+ public void saveSearchState()
+ void onLoaderReset((Loader<Cursor> cursorLoader))
}
class ConcreteCursorListFragment {
# void onListItemClicked(View view)
# CursorLoader createCursorLoader()
# String getListSyncType()
# BaseAdapter createAdapter()
}
class ConcreteListFragment {
# AdapterView.OnItemClickListener createOnItemClickListener()
# BaseAdapter createAdapter()
# void onRefresh()
}
Fragment <|-- AbstractFragment
AbstractFragment <|-- AbstractAdditionalInfoFragment
AbstractFragment *--- DataHolder
AbstractFragment <|-- AbstractTabsFragment
AbstractFragment <|-- AbstractInfoFragment
SharedElement <|.. AbstractInfoFragment
SharedElement <|.. AbstractTabsFragment
AbstractTabsFragment <|-- ConcreteTabsFragment
AbstractInfoFragment <|-- ConcreteInfoFragment
AbstractAdditionalInfoFragment <|-- ConcreteAdditionalInfoFragment
Fragment <|-- AbstractListFragment
AbstractListFragment <|-- AbstractCursorListFragment
AbstractCursorListFragment <|-- ConcreteCursorListFragment
AbstractListFragment <|-- ConcreteListFragment
AbstractInfoFragment *--- AbstractAdditionalInfoFragment
@enduml

View file

@ -0,0 +1,98 @@
@startuml
Actor Activity
participant "AbstractListFragment" as A
participant "AbstractCursorListFragment" as B
participant "ConcreteCursorListFragment" as C
Activity -> A: onCreate
activate A
A -> C: createAdapter()
activate C
C --> A: return adapter
deactivate C
deactivate A
Activity -> B: onCreateView
activate B
B -> A: onCreateView
deactivate B
activate A
A -> A: connect this class as swipe refresh listener
A -> A: setup gridview
activate A
A -> B: createOnItemClickListener
activate B
B --> A: return click listener
deactivate B
deactivate A
A -> A: restore saved state (if any)
A -> A: enable options menu
A -> B:
deactivate A
activate B
B -> B: restore saved search query (if any)
activate B
deactivate B
deactivate B
Activity -> B: onActivityCreated
activate B
B -> LoaderManager: initialize cursor loader
activate LoaderManager
LoaderManager -> B: onCreateLoader
B -> C: createCursorLoader
activate B
activate C
C --> B: return cursorLoader
deactivate C
B --> LoaderManager: return cursorLoader
deactivate B
deactivate B
deactivate LoaderManager
Activity -> B: onStart
Activate B
B ->> LoaderManager: onStart
Activate LoaderManager
B -> B: bind to library sync service
activate B
deactivate B
deactivate B
LoaderManager ->> B: onLoadFinished
Activity -> B: onResume
Activate B
B -> B: register to eventbus
activate B
deactivate B
deactivate B
== UI active ==
...
Activity ->> B: user selects list item
activate B
B -> B: saveSearchState
activate B
deactivate B
B -> C: onListItemClicked(view)
Activate C
C -> Activity: onItemSelected
note over Activity: starts corresponding InfoFragment
deactivate C
deactivate B
== UI inactive ==
Activity -> B: onPause
activate B
B -> B: unregister from eventbus
activate B
deactivate B
deactivate B
Activity -> B: onStop
activate B
B -> B: unbind from library sync service
activate B
deactivate B
deactivate B
@enduml

View file

@ -0,0 +1,113 @@
@startuml
Actor Activity
participant "AbstractFragment" as A
participant "AbstractInfoFragment" as B
participant "ConcreteInfoFragment" as C
participant "AbstractAdditionalInfoFragment" as D
participant "ConcreteAdditionalInfoFragment" as E
participant "RefreshItem" as F
Activity -> A: onCreate
activate A
A -> A: setup DataHolder
activate A
deactivate A
deactivate A
Activity -> B: onCreateView
activate B
B -> B: set poster size to square or rectangular
B -> B: connect this class as swipe refresh listener
B -> C: getAdditionalInfoFragment()
activate C
C -> B: return AbstractAdditionalInfoFragment or null if none
deactivate C
B -> C: setupMediaActionBar()
activate C
C -> B: setOn...Listener(View.OnClickListener)
activate B
C -> B: setOn...Listener(View.OnClickListener)
C -> B: ...
note over C: setting a listener for each\naction button required, will\nmake it visible in the UI
note over B: Make button(s) visible\nin action bar and\nattach listener
B --> C
deactivate B
deactivate C
B -> C: setupFAB(ImageButton FAB)
activate C
note over C: add a listener for the FAB if needed
C -> B: return true to enable the FAB, false to disable it
B -> B: updateView(dataholder)
deactivate C
note left : updateView uses dataholder to fill views
activate B
deactivate B
B --> Activity: return view
deactivate B
Activity -> B: onStart
Activate B
B -> B: bind to library sync service
activate B
deactivate B
deactivate B
Activity -> B: onResume
Activate B
B -> B: register refresh item if it exists
activate B
deactivate B
deactivate B
== UI active ==
...
note over B: user requests a refresh
Activity -> B: onRefresh
activate B
B -> B: getRefreshItem()
B -> C: if no refreshItem then call createRefreshItem()
activate B
activate C
C -> B: return refresh item
deactivate C
deactivate B
B ->> F: startSync()
activate F
F -> F: start LibrarySyncService
B -> D: refresh()
activate D
D -> E: refresh()
activate E
E --> D
deactivate E
D --> B
deactivate D
deactivate B
...
F -> C: onSyncProcessEnded(MediaSyncEvent)
deactivate F
activate C
note over C: update dataholder
C -> B: updateView(dataholder)
deactivate C
...
== UI inactive ==
Activity -> B: onPause
activate B
B -> B: unregister refresh item if it exists
activate B
deactivate B
deactivate B
Activity -> B: onStop
activate B
B -> B: unbind from library sync service
activate B
deactivate B
deactivate B
@enduml

View file

@ -0,0 +1,48 @@
@startuml
Actor Activity
participant "BaseMediaActivity" as A
participant "MediaActivity" as B
Activity -> A: onCreate
activate A
A -> A: set theme
A -> A: setup navigation drawer
group setup action bar
alt new activity
A -> B: getActionBarTitle()
activate B
B -> A:
deactivate B
note over A: set home icon to hamburger icon
else restore action bar
note over A: get home icon and action bar title\nfrom saved instance
end
A -> A: updateActionBar
alt no fragment in layout (new activity)
A -> B: createFragment()
activate B
B -> A:
deactivate B
A -> A: add fragment
end
A -> Activity
deactivate A
...
Activity -> A: onCreateOptionsMenu
activate A
note over A: inflate generic menu items
A -> Activity:
deactivate A
...
note over B: user selects media item
B -> A: showFragment()
activate B
activate A
note over A: sets up the shared element transition\nand updates the dataholder
A -> A: replace current fragment\nwith new fragment
A -> B
deactivate A
deactivate B
@enduml