Copy disabled (too large)
Download .txt
Showing preview only (16,511K chars total). Download the full file to get everything.
Repository: yuliskov/SmartTube
Branch: master
Commit: ce402b5cf741
Files: 2868
Total size: 30.3 MB
Directory structure:
gitextract_iykr0_hr/
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── 1-bug_report.yml
│ │ ├── 2-feature-request.yml
│ │ └── config.yml
│ └── workflows/
│ ├── CI.yml
│ ├── cleanup.yml
│ ├── stale.yml
│ └── virustotal_scan.yml
├── .gitignore
├── .gitmodules
├── .reuse/
│ └── dep5
├── LICENSE
├── README.md
├── build.gradle
├── chatkit/
│ ├── .gitignore
│ ├── LICENSE
│ ├── build.gradle
│ ├── proguard.txt
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── com/
│ │ └── stfalcon/
│ │ └── chatkit/
│ │ ├── commons/
│ │ │ ├── DebouncedOnClickListener.java
│ │ │ ├── ImageLoader.java
│ │ │ ├── InputTrackingRecyclerViewAdapter.java
│ │ │ ├── Style.java
│ │ │ ├── ViewHolder.java
│ │ │ ├── models/
│ │ │ │ ├── IDialog.java
│ │ │ │ ├── IMessage.java
│ │ │ │ ├── IUser.java
│ │ │ │ └── MessageContentType.java
│ │ │ └── widgets/
│ │ │ ├── FocusFixRelativeLayout.java
│ │ │ └── WrapWidthTextView.java
│ │ ├── dialogs/
│ │ │ ├── DialogListStyle.java
│ │ │ ├── DialogsList.java
│ │ │ └── DialogsListAdapter.java
│ │ ├── messages/
│ │ │ ├── MessageHolders.java
│ │ │ ├── MessageInput.java
│ │ │ ├── MessageInputStyle.java
│ │ │ ├── MessagesList.java
│ │ │ ├── MessagesListAdapter.java
│ │ │ ├── MessagesListStyle.java
│ │ │ └── RecyclerScrollMoreListener.java
│ │ └── utils/
│ │ ├── DateFormatter.java
│ │ ├── RoundedImageView.java
│ │ └── ShapeImageView.java
│ └── res/
│ ├── color/
│ │ └── textchange.xml
│ ├── drawable/
│ │ ├── bgchange.xml
│ │ ├── bubble_circle.xml
│ │ ├── shape_incoming_message.xml
│ │ ├── shape_incoming_message_focused.xml
│ │ └── shape_outcoming_message.xml
│ ├── layout/
│ │ ├── item_date_header.xml
│ │ ├── item_dialog.xml
│ │ ├── item_incoming_image_message.xml
│ │ ├── item_incoming_text_message.xml
│ │ ├── item_outcoming_image_message.xml
│ │ ├── item_outcoming_text_message.xml
│ │ └── view_message_input.xml
│ ├── values/
│ │ ├── attrs.xml
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── fonts.xml
│ │ ├── ids.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── values-v21/
│ └── fonts.xml
├── common/
│ ├── .gitignore
│ ├── build.gradle
│ ├── consumer-rules.pro
│ ├── proguard-rules.pro
│ └── src/
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── liskovsoft/
│ │ │ └── smartyoutubetv2/
│ │ │ └── common/
│ │ │ ├── app/
│ │ │ │ ├── models/
│ │ │ │ │ ├── data/
│ │ │ │ │ │ ├── BrowseSection.java
│ │ │ │ │ │ ├── Playlist.java
│ │ │ │ │ │ ├── SettingsGroup.java
│ │ │ │ │ │ ├── SettingsItem.java
│ │ │ │ │ │ ├── SimpleMediaItem.java
│ │ │ │ │ │ ├── Video.java
│ │ │ │ │ │ └── VideoGroup.java
│ │ │ │ │ ├── errors/
│ │ │ │ │ │ ├── CategoryEmptyError.java
│ │ │ │ │ │ ├── ErrorFragmentData.java
│ │ │ │ │ │ ├── PasswordError.java
│ │ │ │ │ │ └── SignInError.java
│ │ │ │ │ ├── playback/
│ │ │ │ │ │ ├── BasePlayerController.java
│ │ │ │ │ │ ├── controllers/
│ │ │ │ │ │ │ ├── AutoFrameRateController.java
│ │ │ │ │ │ │ ├── ChatController.java
│ │ │ │ │ │ │ ├── CommentsController.java
│ │ │ │ │ │ │ ├── HQDialogController.java
│ │ │ │ │ │ │ ├── PlayerUIController.java
│ │ │ │ │ │ │ ├── RemoteController.java
│ │ │ │ │ │ │ ├── SponsorBlockController.java
│ │ │ │ │ │ │ ├── SuggestionsController.java
│ │ │ │ │ │ │ ├── VideoLoaderController.java
│ │ │ │ │ │ │ └── VideoStateController.java
│ │ │ │ │ │ ├── listener/
│ │ │ │ │ │ │ ├── PlayerEngineEventListener.java
│ │ │ │ │ │ │ ├── PlayerEventListener.java
│ │ │ │ │ │ │ ├── PlayerUiEventListener.java
│ │ │ │ │ │ │ └── ViewEventListener.java
│ │ │ │ │ │ ├── manager/
│ │ │ │ │ │ │ ├── PlayerConstants.java
│ │ │ │ │ │ │ ├── PlayerEngine.java
│ │ │ │ │ │ │ ├── PlayerManager.java
│ │ │ │ │ │ │ └── PlayerUI.java
│ │ │ │ │ │ ├── service/
│ │ │ │ │ │ │ └── VideoStateService.java
│ │ │ │ │ │ └── ui/
│ │ │ │ │ │ ├── AbstractCommentsReceiver.java
│ │ │ │ │ │ ├── ChatReceiver.java
│ │ │ │ │ │ ├── ChatReceiverImpl.java
│ │ │ │ │ │ ├── CommentsReceiver.java
│ │ │ │ │ │ ├── OptionCallback.java
│ │ │ │ │ │ ├── OptionCategory.java
│ │ │ │ │ │ ├── OptionItem.java
│ │ │ │ │ │ ├── SeekBarSegment.java
│ │ │ │ │ │ └── UiOptionItem.java
│ │ │ │ │ └── search/
│ │ │ │ │ ├── MediaServiceSearchTagProvider.java
│ │ │ │ │ ├── PrefsSearchTagsProvider.java
│ │ │ │ │ ├── SearchTagsProvider.java
│ │ │ │ │ └── vineyard/
│ │ │ │ │ ├── Option.java
│ │ │ │ │ ├── Tag.java
│ │ │ │ │ └── User.java
│ │ │ │ ├── presenters/
│ │ │ │ │ ├── AddDevicePresenter.java
│ │ │ │ │ ├── AppDialogPresenter.java
│ │ │ │ │ ├── BrowsePresenter.java
│ │ │ │ │ ├── ChannelPresenter.java
│ │ │ │ │ ├── ChannelUploadsPresenter.java
│ │ │ │ │ ├── DetailsPresenter.java
│ │ │ │ │ ├── GoogleSignInPresenter.java
│ │ │ │ │ ├── PlaybackPresenter.java
│ │ │ │ │ ├── SearchPresenter.java
│ │ │ │ │ ├── SignInPresenter.java
│ │ │ │ │ ├── SplashPresenter.java
│ │ │ │ │ ├── WebBrowserPresenter.java
│ │ │ │ │ ├── YTSignInPresenter.java
│ │ │ │ │ ├── base/
│ │ │ │ │ │ └── BasePresenter.java
│ │ │ │ │ ├── dialogs/
│ │ │ │ │ │ ├── ATVBridgePresenter.java
│ │ │ │ │ │ ├── AccountSelectionPresenter.java
│ │ │ │ │ │ ├── AmazonBridgePresenter.java
│ │ │ │ │ │ ├── AppUpdatePresenter.java
│ │ │ │ │ │ ├── BootDialogPresenter.java
│ │ │ │ │ │ ├── BridgePresenter.java
│ │ │ │ │ │ ├── QuickRestorePresenter.java
│ │ │ │ │ │ ├── StableRestorePresenter.java
│ │ │ │ │ │ ├── VideoActionPresenter.java
│ │ │ │ │ │ └── menu/
│ │ │ │ │ │ ├── BaseMenuPresenter.java
│ │ │ │ │ │ ├── ChannelUploadsMenuPresenter.java
│ │ │ │ │ │ ├── SectionMenuPresenter.java
│ │ │ │ │ │ ├── VideoMenuPresenter.java
│ │ │ │ │ │ └── providers/
│ │ │ │ │ │ ├── ContextMenuManager.java
│ │ │ │ │ │ ├── ContextMenuProvider.java
│ │ │ │ │ │ └── channelgroup/
│ │ │ │ │ │ ├── ChannelGroupMenuProvider.java
│ │ │ │ │ │ ├── ChannelGroupServiceWrapper.java
│ │ │ │ │ │ ├── RemoveGroupMenuProvider.java
│ │ │ │ │ │ └── RenameGroupMenuProvider.java
│ │ │ │ │ ├── interfaces/
│ │ │ │ │ │ ├── Presenter.java
│ │ │ │ │ │ ├── SectionPresenter.java
│ │ │ │ │ │ └── VideoGroupPresenter.java
│ │ │ │ │ ├── service/
│ │ │ │ │ │ └── SidebarService.java
│ │ │ │ │ └── settings/
│ │ │ │ │ ├── AboutSettingsPresenter.java
│ │ │ │ │ ├── AboutSimpleSettingsPresenter.java
│ │ │ │ │ ├── AccountSettingsPresenter.java
│ │ │ │ │ ├── AutoFrameRateSettingsPresenter.java
│ │ │ │ │ ├── BackupSettingsPresenter.java
│ │ │ │ │ ├── DeArrowSettingsPresenter.java
│ │ │ │ │ ├── GeneralSettingsPresenter.java
│ │ │ │ │ ├── LanguageSettingsPresenter.java
│ │ │ │ │ ├── MainUISettingsPresenter.java
│ │ │ │ │ ├── PlayerSettingsPresenter.java
│ │ │ │ │ ├── RemoteControlSettingsPresenter.java
│ │ │ │ │ ├── SearchSettingsPresenter.java
│ │ │ │ │ ├── SponsorBlockSettingsPresenter.java
│ │ │ │ │ ├── SubtitleSettingsPresenter.java
│ │ │ │ │ └── UIScaleSettingsPresenter.java
│ │ │ │ └── views/
│ │ │ │ ├── AddDeviceView.java
│ │ │ │ ├── AppDialogView.java
│ │ │ │ ├── AppUpdateView.java
│ │ │ │ ├── BrowseView.java
│ │ │ │ ├── ChannelUploadsView.java
│ │ │ │ ├── ChannelView.java
│ │ │ │ ├── DetailsView.java
│ │ │ │ ├── PlaybackView.java
│ │ │ │ ├── SearchView.java
│ │ │ │ ├── SignInView.java
│ │ │ │ ├── SplashView.java
│ │ │ │ ├── ViewManager.java
│ │ │ │ └── WebBrowserView.java
│ │ │ ├── autoframerate/
│ │ │ │ ├── AutoFrameRateHelper.java
│ │ │ │ ├── ModeSyncManager.java
│ │ │ │ └── internal/
│ │ │ │ ├── DisplayHolder.java
│ │ │ │ ├── DisplaySyncHelper.java
│ │ │ │ ├── UhdHelper.java
│ │ │ │ └── UhdHelperListener.java
│ │ │ ├── exoplayer/
│ │ │ │ ├── ExoMediaSourceFactory.java
│ │ │ │ ├── LiveDashManifestParser.java
│ │ │ │ ├── controller/
│ │ │ │ │ ├── ExoPlayerController.java
│ │ │ │ │ └── PlayerView.java
│ │ │ │ ├── errors/
│ │ │ │ │ ├── DashDefaultLoadErrorHandlingPolicy.java
│ │ │ │ │ ├── SabrDefaultLoadErrorHandlingPolicy.java
│ │ │ │ │ └── TrackErrorFixer.java
│ │ │ │ ├── other/
│ │ │ │ │ ├── DebugInfoManager.java
│ │ │ │ │ ├── ExoPlayerInitializer.java
│ │ │ │ │ ├── SubtitleManager.java
│ │ │ │ │ ├── VideoZoomManager.java
│ │ │ │ │ └── VolumeBooster.java
│ │ │ │ ├── selector/
│ │ │ │ │ ├── ExoFormatItem.java
│ │ │ │ │ ├── FormatItem.java
│ │ │ │ │ ├── TrackInfoFormatter2.java
│ │ │ │ │ ├── TrackSelectorManager.java
│ │ │ │ │ ├── TrackSelectorUtil.java
│ │ │ │ │ └── track/
│ │ │ │ │ ├── AudioTrack.java
│ │ │ │ │ ├── MediaTrack.java
│ │ │ │ │ ├── SubtitleTrack.java
│ │ │ │ │ └── VideoTrack.java
│ │ │ │ └── versions/
│ │ │ │ ├── ExoUtils.java
│ │ │ │ ├── renderer/
│ │ │ │ │ ├── CustomOverridesRenderersFactory.java
│ │ │ │ │ ├── CustomRenderersFactoryBase.java
│ │ │ │ │ ├── DebugInfoMediaCodecVideoRenderer.java
│ │ │ │ │ ├── DelayMediaCodecAudioRenderer.java
│ │ │ │ │ └── TweaksMediaCodecVideoRenderer.java
│ │ │ │ └── selector/
│ │ │ │ ├── BlacklistMediaCodecSelector.java
│ │ │ │ ├── RestoreTrackSelector.java
│ │ │ │ └── backport/
│ │ │ │ └── Definition.java
│ │ │ ├── misc/
│ │ │ │ ├── AppDataSourceManager.java
│ │ │ │ ├── BackgroundPlaybackService.java
│ │ │ │ ├── BackupAndRestoreHelper.java
│ │ │ │ ├── BackupAndRestoreManager.java
│ │ │ │ ├── BackupReceiverActivity.java
│ │ │ │ ├── BrowseProcessor.java
│ │ │ │ ├── BrowseProcessorManager.java
│ │ │ │ ├── CrashRestorer.java
│ │ │ │ ├── DeArrowProcessor.java
│ │ │ │ ├── GDriveBackupManager.java
│ │ │ │ ├── GDriveBackupManagerOld.java
│ │ │ │ ├── GDriveBackupWorker.java
│ │ │ │ ├── GlobalKeyTranslator.java
│ │ │ │ ├── KeyTranslator.java
│ │ │ │ ├── LocalDriveBackupWorker.java
│ │ │ │ ├── MediaServiceManager.java
│ │ │ │ ├── MotherActivity.java
│ │ │ │ ├── PlayerKeyTranslator.java
│ │ │ │ ├── RemoteControlReceiver.java
│ │ │ │ ├── RemoteControlService.java
│ │ │ │ ├── RemoteControlWorker.java
│ │ │ │ ├── ScreensaverManager.java
│ │ │ │ ├── SharedPreferencesHelper.java
│ │ │ │ ├── StreamReminderService.java
│ │ │ │ ├── TickleManager.java
│ │ │ │ ├── UnlocalizedTitleProcessor.java
│ │ │ │ ├── ZipHelper.java
│ │ │ │ └── ZipHelper2.java
│ │ │ ├── prefs/
│ │ │ │ ├── AccountsData.java
│ │ │ │ ├── AppPrefs.java
│ │ │ │ ├── BlockedChannelData.java
│ │ │ │ ├── DeArrowData.java
│ │ │ │ ├── GeneralData.java
│ │ │ │ ├── HiddenPrefs.java
│ │ │ │ ├── MainUIData.java
│ │ │ │ ├── PlayerData.java
│ │ │ │ ├── PlayerTweaksData.java
│ │ │ │ ├── RemoteControlData.java
│ │ │ │ ├── SearchData.java
│ │ │ │ ├── SponsorBlockData.java
│ │ │ │ └── common/
│ │ │ │ ├── DataChangeBase.java
│ │ │ │ └── DataSaverBase.java
│ │ │ ├── proxy/
│ │ │ │ ├── PasswdInetSocketAddress.java
│ │ │ │ ├── PasswdURI.java
│ │ │ │ ├── Proxy.java
│ │ │ │ ├── ProxyManager.java
│ │ │ │ └── WebProxyDialog.java
│ │ │ └── utils/
│ │ │ ├── AppDialogUtil.java
│ │ │ ├── ClickbaitRemover.java
│ │ │ ├── CopyOnWriteHashList.java
│ │ │ ├── HttpURLConnectionUtils.java
│ │ │ ├── IntentExtractor.java
│ │ │ ├── LoadingManager.java
│ │ │ ├── SimpleEditDialog.java
│ │ │ ├── TvQuickActions.java
│ │ │ ├── UserAgentManager.java
│ │ │ └── Utils.java
│ │ └── res/
│ │ ├── layout/
│ │ │ ├── debug_view.xml
│ │ │ ├── dim_container.xml
│ │ │ ├── simple_edit_dialog.xml
│ │ │ └── web_proxy_dialog.xml
│ │ ├── values/
│ │ │ ├── colors.xml
│ │ │ ├── countries.xml
│ │ │ ├── dimens.xml
│ │ │ ├── donations.xml
│ │ │ ├── feedback.xml
│ │ │ ├── ids.xml
│ │ │ ├── languages.xml
│ │ │ ├── strings.xml
│ │ │ ├── styles.xml
│ │ │ ├── unlocalized-strings.xml
│ │ │ └── update_urls.xml
│ │ ├── values-ar/
│ │ │ └── strings.xml
│ │ ├── values-az/
│ │ │ └── strings.xml
│ │ ├── values-bg/
│ │ │ └── strings.xml
│ │ ├── values-ca/
│ │ │ └── strings.xml
│ │ ├── values-cs/
│ │ │ └── strings.xml
│ │ ├── values-da/
│ │ │ └── strings.xml
│ │ ├── values-de/
│ │ │ └── strings.xml
│ │ ├── values-el/
│ │ │ └── strings.xml
│ │ ├── values-es/
│ │ │ └── strings.xml
│ │ ├── values-et/
│ │ │ └── strings.xml
│ │ ├── values-fa-rIR/
│ │ │ └── strings.xml
│ │ ├── values-fi/
│ │ │ └── strings.xml
│ │ ├── values-fr/
│ │ │ └── strings.xml
│ │ ├── values-gl-rES/
│ │ │ └── strings.xml
│ │ ├── values-he/
│ │ │ └── strings.xml
│ │ ├── values-hi/
│ │ │ └── strings.xml
│ │ ├── values-hr/
│ │ │ └── strings.xml
│ │ ├── values-hu/
│ │ │ └── strings.xml
│ │ ├── values-hy/
│ │ │ └── strings.xml
│ │ ├── values-in/
│ │ │ └── strings.xml
│ │ ├── values-it/
│ │ │ └── strings.xml
│ │ ├── values-iw/
│ │ │ └── strings.xml
│ │ ├── values-ja/
│ │ │ └── strings.xml
│ │ ├── values-ko/
│ │ │ └── strings.xml
│ │ ├── values-lt/
│ │ │ └── strings.xml
│ │ ├── values-lv/
│ │ │ └── strings.xml
│ │ ├── values-mo/
│ │ │ └── strings.xml
│ │ ├── values-nb/
│ │ │ └── strings.xml
│ │ ├── values-nl/
│ │ │ └── strings.xml
│ │ ├── values-pl/
│ │ │ └── strings.xml
│ │ ├── values-pt-rBR/
│ │ │ └── strings.xml
│ │ ├── values-pt-rPT/
│ │ │ └── strings.xml
│ │ ├── values-ro/
│ │ │ └── strings.xml
│ │ ├── values-ru/
│ │ │ └── strings.xml
│ │ ├── values-sk/
│ │ │ └── strings.xml
│ │ ├── values-sl/
│ │ │ └── strings.xml
│ │ ├── values-sq/
│ │ │ └── strings.xml
│ │ ├── values-sr/
│ │ │ └── strings.xml
│ │ ├── values-sv/
│ │ │ └── strings.xml
│ │ ├── values-te/
│ │ │ └── strings.xml
│ │ ├── values-th/
│ │ │ └── strings.xml
│ │ ├── values-tr/
│ │ │ └── strings.xml
│ │ ├── values-uk/
│ │ │ └── strings.xml
│ │ ├── values-vi/
│ │ │ └── strings.xml
│ │ ├── values-zh/
│ │ │ └── strings.xml
│ │ ├── values-zh-rTW/
│ │ │ └── strings.xml
│ │ ├── volume-fa/
│ │ │ └── strings.xml
│ │ └── xml/
│ │ └── app_prefs.xml
│ ├── stbeta/
│ │ └── res/
│ │ └── values/
│ │ └── update_urls.xml
│ └── ststable/
│ └── res/
│ └── values/
│ └── update_urls.xml
├── crowdin.yml
├── doubletapplayerview/
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── build.gradle
│ ├── consumer-rules.pro
│ ├── proguard-rules.pro
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── com/
│ │ └── github/
│ │ └── vkay94/
│ │ └── dtpv/
│ │ ├── DoubleTapPlayerAdapter.kt
│ │ ├── DoubleTapPlayerView.kt
│ │ ├── DoubleTapPlayerViewImpl.kt
│ │ ├── PlayerDoubleTapListener.java
│ │ ├── SeekListener.kt
│ │ └── youtube/
│ │ ├── YouTubeOverlay.kt
│ │ └── views/
│ │ ├── CircleClipTapView.kt
│ │ └── YouTubeSecondsView.kt
│ └── res/
│ ├── drawable/
│ │ └── ic_play_triangle.xml
│ ├── layout/
│ │ ├── yt_overlay.xml
│ │ └── yt_seconds_view.xml
│ ├── values/
│ │ ├── dtpv.xml
│ │ ├── plurals.xml
│ │ ├── public.xml
│ │ └── yt_overlay.xml
│ ├── values-af/
│ │ └── plurals.xml
│ ├── values-am/
│ │ └── plurals.xml
│ ├── values-ar/
│ │ └── plurals.xml
│ ├── values-az/
│ │ └── plurals.xml
│ ├── values-b+sr+Latn/
│ │ └── plurals.xml
│ ├── values-be/
│ │ └── plurals.xml
│ ├── values-bg/
│ │ └── plurals.xml
│ ├── values-bn/
│ │ └── plurals.xml
│ ├── values-bs/
│ │ └── plurals.xml
│ ├── values-ca/
│ │ └── plurals.xml
│ ├── values-cs/
│ │ └── plurals.xml
│ ├── values-da/
│ │ └── plurals.xml
│ ├── values-de/
│ │ └── plurals.xml
│ ├── values-el/
│ │ └── plurals.xml
│ ├── values-en-rGB/
│ │ └── plurals.xml
│ ├── values-en-rIN/
│ │ └── plurals.xml
│ ├── values-es/
│ │ └── plurals.xml
│ ├── values-es-rUS/
│ │ └── plurals.xml
│ ├── values-et/
│ │ └── plurals.xml
│ ├── values-eu/
│ │ └── plurals.xml
│ ├── values-fa/
│ │ └── plurals.xml
│ ├── values-fi/
│ │ └── plurals.xml
│ ├── values-fr/
│ │ └── plurals.xml
│ ├── values-fr-rCA/
│ │ └── plurals.xml
│ ├── values-gl/
│ │ └── plurals.xml
│ ├── values-gu/
│ │ └── plurals.xml
│ ├── values-hi/
│ │ └── plurals.xml
│ ├── values-hr/
│ │ └── plurals.xml
│ ├── values-hu/
│ │ └── plurals.xml
│ ├── values-hy/
│ │ └── plurals.xml
│ ├── values-in/
│ │ └── plurals.xml
│ ├── values-is/
│ │ └── plurals.xml
│ ├── values-it/
│ │ └── plurals.xml
│ ├── values-iw/
│ │ └── plurals.xml
│ ├── values-ja/
│ │ └── plurals.xml
│ ├── values-ka/
│ │ └── plurals.xml
│ ├── values-kk/
│ │ └── plurals.xml
│ ├── values-km/
│ │ └── plurals.xml
│ ├── values-kn/
│ │ └── plurals.xml
│ ├── values-ko/
│ │ └── plurals.xml
│ ├── values-ky/
│ │ └── plurals.xml
│ ├── values-lo/
│ │ └── plurals.xml
│ ├── values-lt/
│ │ └── plurals.xml
│ ├── values-lv/
│ │ └── plurals.xml
│ ├── values-mk/
│ │ └── plurals.xml
│ ├── values-ml/
│ │ └── plurals.xml
│ ├── values-mn/
│ │ └── plurals.xml
│ ├── values-mr/
│ │ └── plurals.xml
│ ├── values-ms/
│ │ └── plurals.xml
│ ├── values-my/
│ │ └── plurals.xml
│ ├── values-nb/
│ │ └── plurals.xml
│ ├── values-ne/
│ │ └── plurals.xml
│ ├── values-nl/
│ │ └── plurals.xml
│ ├── values-pa/
│ │ └── plurals.xml
│ ├── values-pl/
│ │ └── plurals.xml
│ ├── values-pt-rBR/
│ │ └── plurals.xml
│ ├── values-pt-rPT/
│ │ └── plurals.xml
│ ├── values-ro/
│ │ └── plurals.xml
│ ├── values-ru/
│ │ └── plurals.xml
│ ├── values-si/
│ │ └── plurals.xml
│ ├── values-sk/
│ │ └── plurals.xml
│ ├── values-sl/
│ │ └── plurals.xml
│ ├── values-sq/
│ │ └── plurals.xml
│ ├── values-sr/
│ │ └── plurals.xml
│ ├── values-sv/
│ │ └── plurals.xml
│ ├── values-sw/
│ │ └── plurals.xml
│ ├── values-ta/
│ │ └── plurals.xml
│ ├── values-te/
│ │ └── plurals.xml
│ ├── values-th/
│ │ └── plurals.xml
│ ├── values-tl/
│ │ └── plurals.xml
│ ├── values-tr/
│ │ └── plurals.xml
│ ├── values-uk/
│ │ └── plurals.xml
│ ├── values-ur/
│ │ └── plurals.xml
│ ├── values-uz/
│ │ └── plurals.xml
│ ├── values-vi/
│ │ └── plurals.xml
│ ├── values-zh-rCN/
│ │ └── plurals.xml
│ ├── values-zh-rHK/
│ │ └── plurals.xml
│ ├── values-zh-rTW/
│ │ └── plurals.xml
│ └── values-zu/
│ └── plurals.xml
├── exoplayer-amzn-2.10.6/
│ ├── .gitignore
│ ├── .hgignore
│ ├── CONTRIBUTING.md
│ ├── LICENSE
│ ├── README-ORIGINAL.md
│ ├── README.md
│ ├── RELEASENOTES.md
│ ├── build.gradle
│ ├── constants.gradle
│ ├── core_settings.gradle
│ ├── demos/
│ │ ├── README.md
│ │ ├── cast/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ ├── proguard-rules.txt
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── castdemo/
│ │ │ │ ├── DefaultReceiverPlayerManager.java
│ │ │ │ ├── DemoUtil.java
│ │ │ │ ├── MainActivity.java
│ │ │ │ └── PlayerManager.java
│ │ │ └── res/
│ │ │ ├── drawable/
│ │ │ │ └── ic_plus.xml
│ │ │ ├── layout/
│ │ │ │ ├── cast_context_error.xml
│ │ │ │ ├── main_activity.xml
│ │ │ │ └── sample_list.xml
│ │ │ ├── menu/
│ │ │ │ └── menu.xml
│ │ │ └── values/
│ │ │ └── strings.xml
│ │ ├── ima/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── imademo/
│ │ │ │ ├── MainActivity.java
│ │ │ │ └── PlayerManager.java
│ │ │ └── res/
│ │ │ ├── layout/
│ │ │ │ └── main_activity.xml
│ │ │ └── values/
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ └── main/
│ │ ├── README.md
│ │ ├── build.gradle
│ │ ├── proguard-rules.txt
│ │ └── src/
│ │ └── main/
│ │ ├── AndroidManifest.xml
│ │ ├── assets/
│ │ │ └── media.exolist.json
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── demo/
│ │ │ ├── DemoApplication.java
│ │ │ ├── DemoDownloadService.java
│ │ │ ├── DownloadTracker.java
│ │ │ ├── PlayerActivity.java
│ │ │ ├── SampleChooserActivity.java
│ │ │ └── TrackSelectionDialog.java
│ │ └── res/
│ │ ├── layout/
│ │ │ ├── player_activity.xml
│ │ │ ├── sample_chooser_activity.xml
│ │ │ ├── sample_list_item.xml
│ │ │ └── track_selection_dialog.xml
│ │ ├── menu/
│ │ │ └── sample_chooser_menu.xml
│ │ └── values/
│ │ ├── strings.xml
│ │ └── styles.xml
│ ├── extensions/
│ │ ├── README.md
│ │ ├── cast/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── ext/
│ │ │ │ └── cast/
│ │ │ │ ├── CastPlayer.java
│ │ │ │ ├── CastTimeline.java
│ │ │ │ ├── CastTimelineTracker.java
│ │ │ │ ├── CastUtils.java
│ │ │ │ ├── DefaultCastOptionsProvider.java
│ │ │ │ ├── MediaItem.java
│ │ │ │ ├── MediaItemQueue.java
│ │ │ │ └── SessionAvailabilityListener.java
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── cast/
│ │ │ ├── CastTimelineTrackerTest.java
│ │ │ └── MediaItemTest.java
│ │ ├── cronet/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── ext/
│ │ │ │ └── cronet/
│ │ │ │ ├── ByteArrayUploadDataProvider.java
│ │ │ │ ├── CronetDataSource.java
│ │ │ │ ├── CronetDataSourceFactory.java
│ │ │ │ └── CronetEngineWrapper.java
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── cronet/
│ │ │ ├── ByteArrayUploadDataProviderTest.java
│ │ │ └── CronetDataSourceTest.java
│ │ ├── ffmpeg/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ ├── proguard-rules.txt
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── java/
│ │ │ │ │ └── com/
│ │ │ │ │ └── google/
│ │ │ │ │ └── android/
│ │ │ │ │ └── exoplayer2/
│ │ │ │ │ └── ext/
│ │ │ │ │ └── ffmpeg/
│ │ │ │ │ ├── FfmpegAudioRenderer.java
│ │ │ │ │ ├── FfmpegDecoder.java
│ │ │ │ │ ├── FfmpegDecoderException.java
│ │ │ │ │ └── FfmpegLibrary.java
│ │ │ │ └── jni/
│ │ │ │ ├── Android.mk
│ │ │ │ ├── Application.mk
│ │ │ │ └── ffmpeg_jni.cc
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── ffmpeg/
│ │ │ └── DefaultRenderersFactoryTest.java
│ │ ├── flac/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ ├── proguard-rules.txt
│ │ │ └── src/
│ │ │ ├── androidTest/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── assets/
│ │ │ │ │ ├── bear-flac.mka
│ │ │ │ │ ├── bear.flac
│ │ │ │ │ ├── bear.flac.0.dump
│ │ │ │ │ ├── bear.flac.1.dump
│ │ │ │ │ ├── bear.flac.2.dump
│ │ │ │ │ ├── bear.flac.3.dump
│ │ │ │ │ ├── bear_no_seek.flac
│ │ │ │ │ ├── bear_with_id3.flac
│ │ │ │ │ ├── bear_with_id3.flac.0.dump
│ │ │ │ │ ├── bear_with_id3.flac.1.dump
│ │ │ │ │ ├── bear_with_id3.flac.2.dump
│ │ │ │ │ └── bear_with_id3.flac.3.dump
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── ext/
│ │ │ │ └── flac/
│ │ │ │ ├── FlacBinarySearchSeekerTest.java
│ │ │ │ ├── FlacExtractorSeekTest.java
│ │ │ │ ├── FlacExtractorTest.java
│ │ │ │ └── FlacPlaybackTest.java
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── java/
│ │ │ │ │ └── com/
│ │ │ │ │ └── google/
│ │ │ │ │ └── android/
│ │ │ │ │ └── exoplayer2/
│ │ │ │ │ └── ext/
│ │ │ │ │ └── flac/
│ │ │ │ │ ├── FlacBinarySearchSeeker.java
│ │ │ │ │ ├── FlacDecoder.java
│ │ │ │ │ ├── FlacDecoderException.java
│ │ │ │ │ ├── FlacDecoderJni.java
│ │ │ │ │ ├── FlacExtractor.java
│ │ │ │ │ ├── FlacLibrary.java
│ │ │ │ │ └── LibflacAudioRenderer.java
│ │ │ │ └── jni/
│ │ │ │ ├── Android.mk
│ │ │ │ ├── Application.mk
│ │ │ │ ├── flac_jni.cc
│ │ │ │ ├── flac_parser.cc
│ │ │ │ ├── flac_sources.mk
│ │ │ │ └── include/
│ │ │ │ ├── data_source.h
│ │ │ │ └── flac_parser.h
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── flac/
│ │ │ ├── DefaultExtractorsFactoryTest.java
│ │ │ └── DefaultRenderersFactoryTest.java
│ │ ├── gvr/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── ext/
│ │ │ │ └── gvr/
│ │ │ │ ├── GvrAudioProcessor.java
│ │ │ │ └── GvrPlayerActivity.java
│ │ │ └── res/
│ │ │ ├── layout/
│ │ │ │ └── vr_ui.xml
│ │ │ ├── values/
│ │ │ │ └── styles.xml
│ │ │ └── values-v21/
│ │ │ └── styles.xml
│ │ ├── ima/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ ├── proguard-rules.txt
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── ext/
│ │ │ │ └── ima/
│ │ │ │ └── ImaAdsLoader.java
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── ima/
│ │ │ ├── FakeAd.java
│ │ │ ├── FakeAdsLoader.java
│ │ │ ├── FakeAdsRequest.java
│ │ │ ├── FakePlayer.java
│ │ │ ├── ImaAdsLoaderTest.java
│ │ │ └── SingletonImaFactory.java
│ │ ├── jobdispatcher/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── jobdispatcher/
│ │ │ └── JobDispatcherScheduler.java
│ │ ├── leanback/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── leanback/
│ │ │ └── LeanbackPlayerAdapter.java
│ │ ├── mediasession/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── ext/
│ │ │ │ └── mediasession/
│ │ │ │ ├── MediaSessionConnector.java
│ │ │ │ ├── RepeatModeActionProvider.java
│ │ │ │ ├── TimelineQueueEditor.java
│ │ │ │ └── TimelineQueueNavigator.java
│ │ │ └── res/
│ │ │ ├── drawable-anydpi-v21/
│ │ │ │ ├── exo_media_action_repeat_all.xml
│ │ │ │ ├── exo_media_action_repeat_off.xml
│ │ │ │ └── exo_media_action_repeat_one.xml
│ │ │ ├── values/
│ │ │ │ └── strings.xml
│ │ │ ├── values-af/
│ │ │ │ └── strings.xml
│ │ │ ├── values-am/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ar/
│ │ │ │ └── strings.xml
│ │ │ ├── values-az/
│ │ │ │ └── strings.xml
│ │ │ ├── values-b+sr+Latn/
│ │ │ │ └── strings.xml
│ │ │ ├── values-be/
│ │ │ │ └── strings.xml
│ │ │ ├── values-bg/
│ │ │ │ └── strings.xml
│ │ │ ├── values-bn/
│ │ │ │ └── strings.xml
│ │ │ ├── values-bs/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ca/
│ │ │ │ └── strings.xml
│ │ │ ├── values-cs/
│ │ │ │ └── strings.xml
│ │ │ ├── values-da/
│ │ │ │ └── strings.xml
│ │ │ ├── values-de/
│ │ │ │ └── strings.xml
│ │ │ ├── values-el/
│ │ │ │ └── strings.xml
│ │ │ ├── values-en-rAU/
│ │ │ │ └── strings.xml
│ │ │ ├── values-en-rGB/
│ │ │ │ └── strings.xml
│ │ │ ├── values-en-rIN/
│ │ │ │ └── strings.xml
│ │ │ ├── values-es/
│ │ │ │ └── strings.xml
│ │ │ ├── values-es-rUS/
│ │ │ │ └── strings.xml
│ │ │ ├── values-et/
│ │ │ │ └── strings.xml
│ │ │ ├── values-eu/
│ │ │ │ └── strings.xml
│ │ │ ├── values-fa/
│ │ │ │ └── strings.xml
│ │ │ ├── values-fi/
│ │ │ │ └── strings.xml
│ │ │ ├── values-fr/
│ │ │ │ └── strings.xml
│ │ │ ├── values-fr-rCA/
│ │ │ │ └── strings.xml
│ │ │ ├── values-gl/
│ │ │ │ └── strings.xml
│ │ │ ├── values-gu/
│ │ │ │ └── strings.xml
│ │ │ ├── values-hi/
│ │ │ │ └── strings.xml
│ │ │ ├── values-hr/
│ │ │ │ └── strings.xml
│ │ │ ├── values-hu/
│ │ │ │ └── strings.xml
│ │ │ ├── values-hy/
│ │ │ │ └── strings.xml
│ │ │ ├── values-in/
│ │ │ │ └── strings.xml
│ │ │ ├── values-is/
│ │ │ │ └── strings.xml
│ │ │ ├── values-it/
│ │ │ │ └── strings.xml
│ │ │ ├── values-iw/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ja/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ka/
│ │ │ │ └── strings.xml
│ │ │ ├── values-kk/
│ │ │ │ └── strings.xml
│ │ │ ├── values-km/
│ │ │ │ └── strings.xml
│ │ │ ├── values-kn/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ko/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ky/
│ │ │ │ └── strings.xml
│ │ │ ├── values-lo/
│ │ │ │ └── strings.xml
│ │ │ ├── values-lt/
│ │ │ │ └── strings.xml
│ │ │ ├── values-lv/
│ │ │ │ └── strings.xml
│ │ │ ├── values-mk/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ml/
│ │ │ │ └── strings.xml
│ │ │ ├── values-mn/
│ │ │ │ └── strings.xml
│ │ │ ├── values-mr/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ms/
│ │ │ │ └── strings.xml
│ │ │ ├── values-my/
│ │ │ │ └── strings.xml
│ │ │ ├── values-nb/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ne/
│ │ │ │ └── strings.xml
│ │ │ ├── values-nl/
│ │ │ │ └── strings.xml
│ │ │ ├── values-pa/
│ │ │ │ └── strings.xml
│ │ │ ├── values-pl/
│ │ │ │ └── strings.xml
│ │ │ ├── values-pt/
│ │ │ │ └── strings.xml
│ │ │ ├── values-pt-rPT/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ro/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ru/
│ │ │ │ └── strings.xml
│ │ │ ├── values-si/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sk/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sl/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sq/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sr/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sv/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sw/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ta/
│ │ │ │ └── strings.xml
│ │ │ ├── values-te/
│ │ │ │ └── strings.xml
│ │ │ ├── values-th/
│ │ │ │ └── strings.xml
│ │ │ ├── values-tl/
│ │ │ │ └── strings.xml
│ │ │ ├── values-tr/
│ │ │ │ └── strings.xml
│ │ │ ├── values-uk/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ur/
│ │ │ │ └── strings.xml
│ │ │ ├── values-uz/
│ │ │ │ └── strings.xml
│ │ │ ├── values-vi/
│ │ │ │ └── strings.xml
│ │ │ ├── values-zh-rCN/
│ │ │ │ └── strings.xml
│ │ │ ├── values-zh-rHK/
│ │ │ │ └── strings.xml
│ │ │ ├── values-zh-rTW/
│ │ │ │ └── strings.xml
│ │ │ └── values-zu/
│ │ │ └── strings.xml
│ │ ├── okhttp/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ ├── proguard-rules.txt
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── okhttp/
│ │ │ ├── OkHttpDataSource.java
│ │ │ └── OkHttpDataSourceFactory.java
│ │ ├── opus/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ ├── proguard-rules.txt
│ │ │ └── src/
│ │ │ ├── androidTest/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── assets/
│ │ │ │ │ └── bear-opus.webm
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── ext/
│ │ │ │ └── opus/
│ │ │ │ └── OpusPlaybackTest.java
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── java/
│ │ │ │ │ └── com/
│ │ │ │ │ └── google/
│ │ │ │ │ └── android/
│ │ │ │ │ └── exoplayer2/
│ │ │ │ │ └── ext/
│ │ │ │ │ └── opus/
│ │ │ │ │ ├── LibopusAudioRenderer.java
│ │ │ │ │ ├── OpusDecoder.java
│ │ │ │ │ ├── OpusDecoderException.java
│ │ │ │ │ └── OpusLibrary.java
│ │ │ │ └── jni/
│ │ │ │ ├── Android.mk
│ │ │ │ ├── Application.mk
│ │ │ │ ├── convert_android_asm.sh
│ │ │ │ ├── libopus.mk
│ │ │ │ └── opus_jni.cc
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── opus/
│ │ │ └── DefaultRenderersFactoryTest.java
│ │ ├── rtmp/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── ext/
│ │ │ │ └── rtmp/
│ │ │ │ ├── RtmpDataSource.java
│ │ │ │ └── RtmpDataSourceFactory.java
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── rtmp/
│ │ │ └── DefaultDataSourceTest.java
│ │ ├── vp9/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ ├── proguard-rules.txt
│ │ │ └── src/
│ │ │ ├── androidTest/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── assets/
│ │ │ │ │ ├── bear-vp9-odd-dimensions.webm
│ │ │ │ │ ├── bear-vp9.webm
│ │ │ │ │ ├── invalid-bitstream.webm
│ │ │ │ │ └── roadtrip-vp92-10bit.webm
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── ext/
│ │ │ │ └── vp9/
│ │ │ │ └── VpxPlaybackTest.java
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── java/
│ │ │ │ │ └── com/
│ │ │ │ │ └── google/
│ │ │ │ │ └── android/
│ │ │ │ │ └── exoplayer2/
│ │ │ │ │ └── ext/
│ │ │ │ │ └── vp9/
│ │ │ │ │ ├── LibvpxVideoRenderer.java
│ │ │ │ │ ├── VpxDecoder.java
│ │ │ │ │ ├── VpxDecoderException.java
│ │ │ │ │ ├── VpxInputBuffer.java
│ │ │ │ │ ├── VpxLibrary.java
│ │ │ │ │ ├── VpxOutputBuffer.java
│ │ │ │ │ ├── VpxOutputBufferRenderer.java
│ │ │ │ │ ├── VpxRenderer.java
│ │ │ │ │ └── VpxVideoSurfaceView.java
│ │ │ │ └── jni/
│ │ │ │ ├── Android.mk
│ │ │ │ ├── Application.mk
│ │ │ │ ├── generate_libvpx_android_configs.sh
│ │ │ │ ├── libvpx.mk
│ │ │ │ └── vpx_jni.cc
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── vp9/
│ │ │ └── DefaultRenderersFactoryTest.java
│ │ └── workmanager/
│ │ ├── README.md
│ │ ├── build.gradle
│ │ └── src/
│ │ └── main/
│ │ ├── AndroidManifest.xml
│ │ └── java/
│ │ └── com/
│ │ └── google/
│ │ └── android/
│ │ └── exoplayer2/
│ │ └── ext/
│ │ └── workmanager/
│ │ └── WorkManagerScheduler.java
│ ├── gradle/
│ │ └── wrapper/
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
│ ├── gradle.properties
│ ├── gradlew
│ ├── gradlew.bat
│ ├── issues/
│ │ └── player-accessed-on-wrong-thread.md
│ ├── javadoc_combined.gradle
│ ├── javadoc_library.gradle
│ ├── javadoc_util.gradle
│ ├── library/
│ │ ├── README.md
│ │ ├── all/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ └── main/
│ │ │ └── AndroidManifest.xml
│ │ ├── core/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ ├── proguard-rules.txt
│ │ │ └── src/
│ │ │ ├── androidTest/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── upstream/
│ │ │ │ └── ContentDataSourceTest.java
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ ├── BasePlayer.java
│ │ │ │ ├── BaseRenderer.java
│ │ │ │ ├── C.java
│ │ │ │ ├── ControlDispatcher.java
│ │ │ │ ├── DefaultControlDispatcher.java
│ │ │ │ ├── DefaultLoadControl.java
│ │ │ │ ├── DefaultMediaClock.java
│ │ │ │ ├── DefaultRenderersFactory.java
│ │ │ │ ├── ExoPlaybackException.java
│ │ │ │ ├── ExoPlayer.java
│ │ │ │ ├── ExoPlayerFactory.java
│ │ │ │ ├── ExoPlayerImpl.java
│ │ │ │ ├── ExoPlayerImplInternal.java
│ │ │ │ ├── ExoPlayerLibraryInfo.java
│ │ │ │ ├── Format.java
│ │ │ │ ├── FormatHolder.java
│ │ │ │ ├── IllegalSeekPositionException.java
│ │ │ │ ├── LoadControl.java
│ │ │ │ ├── MediaPeriodHolder.java
│ │ │ │ ├── MediaPeriodInfo.java
│ │ │ │ ├── MediaPeriodQueue.java
│ │ │ │ ├── NoSampleRenderer.java
│ │ │ │ ├── ParserException.java
│ │ │ │ ├── PlaybackInfo.java
│ │ │ │ ├── PlaybackParameters.java
│ │ │ │ ├── PlaybackPreparer.java
│ │ │ │ ├── Player.java
│ │ │ │ ├── PlayerMessage.java
│ │ │ │ ├── Renderer.java
│ │ │ │ ├── RendererCapabilities.java
│ │ │ │ ├── RendererConfiguration.java
│ │ │ │ ├── RenderersFactory.java
│ │ │ │ ├── SeekParameters.java
│ │ │ │ ├── SimpleExoPlayer.java
│ │ │ │ ├── Timeline.java
│ │ │ │ ├── analytics/
│ │ │ │ │ ├── AnalyticsCollector.java
│ │ │ │ │ ├── AnalyticsListener.java
│ │ │ │ │ └── DefaultAnalyticsListener.java
│ │ │ │ ├── audio/
│ │ │ │ │ ├── Ac3Util.java
│ │ │ │ │ ├── Ac4Util.java
│ │ │ │ │ ├── AudioAttributes.java
│ │ │ │ │ ├── AudioCapabilities.java
│ │ │ │ │ ├── AudioCapabilitiesReceiver.java
│ │ │ │ │ ├── AudioDecoderException.java
│ │ │ │ │ ├── AudioFocusManager.java
│ │ │ │ │ ├── AudioListener.java
│ │ │ │ │ ├── AudioProcessor.java
│ │ │ │ │ ├── AudioRendererEventListener.java
│ │ │ │ │ ├── AudioSink.java
│ │ │ │ │ ├── AudioTimestampPoller.java
│ │ │ │ │ ├── AudioTrackPositionTracker.java
│ │ │ │ │ ├── AuxEffectInfo.java
│ │ │ │ │ ├── BaseAudioProcessor.java
│ │ │ │ │ ├── ChannelMappingAudioProcessor.java
│ │ │ │ │ ├── DefaultAudioSink.java
│ │ │ │ │ ├── DolbyPassthroughAudioTrack.java
│ │ │ │ │ ├── DtsUtil.java
│ │ │ │ │ ├── FloatResamplingAudioProcessor.java
│ │ │ │ │ ├── MediaCodecAudioRenderer.java
│ │ │ │ │ ├── ResamplingAudioProcessor.java
│ │ │ │ │ ├── SilenceSkippingAudioProcessor.java
│ │ │ │ │ ├── SimpleDecoderAudioRenderer.java
│ │ │ │ │ ├── Sonic.java
│ │ │ │ │ ├── SonicAudioProcessor.java
│ │ │ │ │ ├── TeeAudioProcessor.java
│ │ │ │ │ ├── TrimmingAudioProcessor.java
│ │ │ │ │ └── WavUtil.java
│ │ │ │ ├── database/
│ │ │ │ │ ├── DatabaseIOException.java
│ │ │ │ │ ├── DatabaseProvider.java
│ │ │ │ │ ├── DefaultDatabaseProvider.java
│ │ │ │ │ ├── ExoDatabaseProvider.java
│ │ │ │ │ └── VersionTable.java
│ │ │ │ ├── decoder/
│ │ │ │ │ ├── Buffer.java
│ │ │ │ │ ├── CryptoInfo.java
│ │ │ │ │ ├── Decoder.java
│ │ │ │ │ ├── DecoderCounters.java
│ │ │ │ │ ├── DecoderInputBuffer.java
│ │ │ │ │ ├── OutputBuffer.java
│ │ │ │ │ ├── SimpleDecoder.java
│ │ │ │ │ └── SimpleOutputBuffer.java
│ │ │ │ ├── drm/
│ │ │ │ │ ├── ClearKeyUtil.java
│ │ │ │ │ ├── DecryptionException.java
│ │ │ │ │ ├── DecryptionResource.java
│ │ │ │ │ ├── DefaultDrmSession.java
│ │ │ │ │ ├── DefaultDrmSessionEventListener.java
│ │ │ │ │ ├── DefaultDrmSessionManager.java
│ │ │ │ │ ├── DrmInitData.java
│ │ │ │ │ ├── DrmSession.java
│ │ │ │ │ ├── DrmSessionManager.java
│ │ │ │ │ ├── ErrorStateDrmSession.java
│ │ │ │ │ ├── ExoMediaCrypto.java
│ │ │ │ │ ├── ExoMediaDrm.java
│ │ │ │ │ ├── FrameworkMediaCrypto.java
│ │ │ │ │ ├── FrameworkMediaDrm.java
│ │ │ │ │ ├── HttpMediaDrmCallback.java
│ │ │ │ │ ├── KeysExpiredException.java
│ │ │ │ │ ├── LocalMediaDrmCallback.java
│ │ │ │ │ ├── MediaDrmCallback.java
│ │ │ │ │ ├── OfflineLicenseHelper.java
│ │ │ │ │ ├── UnsupportedDrmException.java
│ │ │ │ │ └── WidevineUtil.java
│ │ │ │ ├── extractor/
│ │ │ │ │ ├── BinarySearchSeeker.java
│ │ │ │ │ ├── ChunkIndex.java
│ │ │ │ │ ├── ConstantBitrateSeekMap.java
│ │ │ │ │ ├── DefaultExtractorInput.java
│ │ │ │ │ ├── DefaultExtractorsFactory.java
│ │ │ │ │ ├── DummyExtractorOutput.java
│ │ │ │ │ ├── DummyTrackOutput.java
│ │ │ │ │ ├── Extractor.java
│ │ │ │ │ ├── ExtractorInput.java
│ │ │ │ │ ├── ExtractorOutput.java
│ │ │ │ │ ├── ExtractorsFactory.java
│ │ │ │ │ ├── GaplessInfoHolder.java
│ │ │ │ │ ├── Id3Peeker.java
│ │ │ │ │ ├── MpegAudioHeader.java
│ │ │ │ │ ├── PositionHolder.java
│ │ │ │ │ ├── SeekMap.java
│ │ │ │ │ ├── SeekPoint.java
│ │ │ │ │ ├── TrackOutput.java
│ │ │ │ │ ├── amr/
│ │ │ │ │ │ └── AmrExtractor.java
│ │ │ │ │ ├── flv/
│ │ │ │ │ │ ├── AudioTagPayloadReader.java
│ │ │ │ │ │ ├── FlvExtractor.java
│ │ │ │ │ │ ├── ScriptTagPayloadReader.java
│ │ │ │ │ │ ├── TagPayloadReader.java
│ │ │ │ │ │ └── VideoTagPayloadReader.java
│ │ │ │ │ ├── mkv/
│ │ │ │ │ │ ├── DefaultEbmlReader.java
│ │ │ │ │ │ ├── EbmlProcessor.java
│ │ │ │ │ │ ├── EbmlReader.java
│ │ │ │ │ │ ├── MatroskaExtractor.java
│ │ │ │ │ │ ├── Sniffer.java
│ │ │ │ │ │ └── VarintReader.java
│ │ │ │ │ ├── mp3/
│ │ │ │ │ │ ├── ConstantBitrateSeeker.java
│ │ │ │ │ │ ├── MlltSeeker.java
│ │ │ │ │ │ ├── Mp3Extractor.java
│ │ │ │ │ │ ├── Seeker.java
│ │ │ │ │ │ ├── VbriSeeker.java
│ │ │ │ │ │ └── XingSeeker.java
│ │ │ │ │ ├── mp4/
│ │ │ │ │ │ ├── Atom.java
│ │ │ │ │ │ ├── AtomParsers.java
│ │ │ │ │ │ ├── DefaultSampleValues.java
│ │ │ │ │ │ ├── FixedSampleSizeRechunker.java
│ │ │ │ │ │ ├── FragmentedMp4Extractor.java
│ │ │ │ │ │ ├── MdtaMetadataEntry.java
│ │ │ │ │ │ ├── MetadataUtil.java
│ │ │ │ │ │ ├── Mp4Extractor.java
│ │ │ │ │ │ ├── PsshAtomUtil.java
│ │ │ │ │ │ ├── Sniffer.java
│ │ │ │ │ │ ├── Track.java
│ │ │ │ │ │ ├── TrackEncryptionBox.java
│ │ │ │ │ │ ├── TrackFragment.java
│ │ │ │ │ │ └── TrackSampleTable.java
│ │ │ │ │ ├── ogg/
│ │ │ │ │ │ ├── DefaultOggSeeker.java
│ │ │ │ │ │ ├── FlacReader.java
│ │ │ │ │ │ ├── OggExtractor.java
│ │ │ │ │ │ ├── OggPacket.java
│ │ │ │ │ │ ├── OggPageHeader.java
│ │ │ │ │ │ ├── OggSeeker.java
│ │ │ │ │ │ ├── OpusReader.java
│ │ │ │ │ │ ├── StreamReader.java
│ │ │ │ │ │ ├── VorbisBitArray.java
│ │ │ │ │ │ ├── VorbisReader.java
│ │ │ │ │ │ └── VorbisUtil.java
│ │ │ │ │ ├── rawcc/
│ │ │ │ │ │ └── RawCcExtractor.java
│ │ │ │ │ ├── ts/
│ │ │ │ │ │ ├── Ac3Extractor.java
│ │ │ │ │ │ ├── Ac3Reader.java
│ │ │ │ │ │ ├── Ac4Extractor.java
│ │ │ │ │ │ ├── Ac4Reader.java
│ │ │ │ │ │ ├── AdtsExtractor.java
│ │ │ │ │ │ ├── AdtsReader.java
│ │ │ │ │ │ ├── DefaultTsPayloadReaderFactory.java
│ │ │ │ │ │ ├── DtsReader.java
│ │ │ │ │ │ ├── DvbSubtitleReader.java
│ │ │ │ │ │ ├── ElementaryStreamReader.java
│ │ │ │ │ │ ├── H262Reader.java
│ │ │ │ │ │ ├── H264Reader.java
│ │ │ │ │ │ ├── H265Reader.java
│ │ │ │ │ │ ├── Id3Reader.java
│ │ │ │ │ │ ├── LatmReader.java
│ │ │ │ │ │ ├── MpegAudioReader.java
│ │ │ │ │ │ ├── NalUnitTargetBuffer.java
│ │ │ │ │ │ ├── PesReader.java
│ │ │ │ │ │ ├── PsBinarySearchSeeker.java
│ │ │ │ │ │ ├── PsDurationReader.java
│ │ │ │ │ │ ├── PsExtractor.java
│ │ │ │ │ │ ├── SectionPayloadReader.java
│ │ │ │ │ │ ├── SectionReader.java
│ │ │ │ │ │ ├── SeiReader.java
│ │ │ │ │ │ ├── SpliceInfoSectionReader.java
│ │ │ │ │ │ ├── TsBinarySearchSeeker.java
│ │ │ │ │ │ ├── TsDurationReader.java
│ │ │ │ │ │ ├── TsExtractor.java
│ │ │ │ │ │ ├── TsPayloadReader.java
│ │ │ │ │ │ ├── TsUtil.java
│ │ │ │ │ │ └── UserDataReader.java
│ │ │ │ │ └── wav/
│ │ │ │ │ ├── WavExtractor.java
│ │ │ │ │ ├── WavHeader.java
│ │ │ │ │ └── WavHeaderReader.java
│ │ │ │ ├── mediacodec/
│ │ │ │ │ ├── MediaCodecInfo.java
│ │ │ │ │ ├── MediaCodecRenderer.java
│ │ │ │ │ ├── MediaCodecSelector.java
│ │ │ │ │ ├── MediaCodecUtil.java
│ │ │ │ │ └── MediaFormatUtil.java
│ │ │ │ ├── metadata/
│ │ │ │ │ ├── Metadata.java
│ │ │ │ │ ├── MetadataDecoder.java
│ │ │ │ │ ├── MetadataDecoderFactory.java
│ │ │ │ │ ├── MetadataInputBuffer.java
│ │ │ │ │ ├── MetadataOutput.java
│ │ │ │ │ ├── MetadataRenderer.java
│ │ │ │ │ ├── emsg/
│ │ │ │ │ │ ├── EventMessage.java
│ │ │ │ │ │ ├── EventMessageDecoder.java
│ │ │ │ │ │ └── EventMessageEncoder.java
│ │ │ │ │ ├── flac/
│ │ │ │ │ │ ├── PictureFrame.java
│ │ │ │ │ │ └── VorbisComment.java
│ │ │ │ │ ├── icy/
│ │ │ │ │ │ ├── IcyDecoder.java
│ │ │ │ │ │ ├── IcyHeaders.java
│ │ │ │ │ │ └── IcyInfo.java
│ │ │ │ │ ├── id3/
│ │ │ │ │ │ ├── ApicFrame.java
│ │ │ │ │ │ ├── BinaryFrame.java
│ │ │ │ │ │ ├── ChapterFrame.java
│ │ │ │ │ │ ├── ChapterTocFrame.java
│ │ │ │ │ │ ├── CommentFrame.java
│ │ │ │ │ │ ├── GeobFrame.java
│ │ │ │ │ │ ├── Id3Decoder.java
│ │ │ │ │ │ ├── Id3Frame.java
│ │ │ │ │ │ ├── InternalFrame.java
│ │ │ │ │ │ ├── MlltFrame.java
│ │ │ │ │ │ ├── PrivFrame.java
│ │ │ │ │ │ ├── TextInformationFrame.java
│ │ │ │ │ │ └── UrlLinkFrame.java
│ │ │ │ │ └── scte35/
│ │ │ │ │ ├── PrivateCommand.java
│ │ │ │ │ ├── SpliceCommand.java
│ │ │ │ │ ├── SpliceInfoDecoder.java
│ │ │ │ │ ├── SpliceInsertCommand.java
│ │ │ │ │ ├── SpliceNullCommand.java
│ │ │ │ │ ├── SpliceScheduleCommand.java
│ │ │ │ │ └── TimeSignalCommand.java
│ │ │ │ ├── offline/
│ │ │ │ │ ├── ActionFile.java
│ │ │ │ │ ├── ActionFileUpgradeUtil.java
│ │ │ │ │ ├── DefaultDownloadIndex.java
│ │ │ │ │ ├── DefaultDownloaderFactory.java
│ │ │ │ │ ├── Download.java
│ │ │ │ │ ├── DownloadCursor.java
│ │ │ │ │ ├── DownloadException.java
│ │ │ │ │ ├── DownloadHelper.java
│ │ │ │ │ ├── DownloadIndex.java
│ │ │ │ │ ├── DownloadManager.java
│ │ │ │ │ ├── DownloadProgress.java
│ │ │ │ │ ├── DownloadRequest.java
│ │ │ │ │ ├── DownloadService.java
│ │ │ │ │ ├── Downloader.java
│ │ │ │ │ ├── DownloaderConstructorHelper.java
│ │ │ │ │ ├── DownloaderFactory.java
│ │ │ │ │ ├── FilterableManifest.java
│ │ │ │ │ ├── FilteringManifestParser.java
│ │ │ │ │ ├── ProgressiveDownloader.java
│ │ │ │ │ ├── SegmentDownloader.java
│ │ │ │ │ ├── StreamKey.java
│ │ │ │ │ └── WritableDownloadIndex.java
│ │ │ │ ├── scheduler/
│ │ │ │ │ ├── PlatformScheduler.java
│ │ │ │ │ ├── Requirements.java
│ │ │ │ │ ├── RequirementsWatcher.java
│ │ │ │ │ └── Scheduler.java
│ │ │ │ ├── source/
│ │ │ │ │ ├── AbstractConcatenatedTimeline.java
│ │ │ │ │ ├── AdaptiveMediaSourceEventListener.java
│ │ │ │ │ ├── BaseMediaSource.java
│ │ │ │ │ ├── BehindLiveWindowException.java
│ │ │ │ │ ├── ClippingMediaPeriod.java
│ │ │ │ │ ├── ClippingMediaSource.java
│ │ │ │ │ ├── CompositeMediaSource.java
│ │ │ │ │ ├── CompositeSequenceableLoader.java
│ │ │ │ │ ├── CompositeSequenceableLoaderFactory.java
│ │ │ │ │ ├── ConcatenatingMediaSource.java
│ │ │ │ │ ├── DefaultCompositeSequenceableLoaderFactory.java
│ │ │ │ │ ├── DefaultMediaSourceEventListener.java
│ │ │ │ │ ├── DeferredMediaPeriod.java
│ │ │ │ │ ├── DynamicConcatenatingMediaSource.java
│ │ │ │ │ ├── EmptySampleStream.java
│ │ │ │ │ ├── ExtractorMediaSource.java
│ │ │ │ │ ├── ForwardingTimeline.java
│ │ │ │ │ ├── IcyDataSource.java
│ │ │ │ │ ├── LoopingMediaSource.java
│ │ │ │ │ ├── MediaPeriod.java
│ │ │ │ │ ├── MediaSource.java
│ │ │ │ │ ├── MediaSourceEventListener.java
│ │ │ │ │ ├── MergingMediaPeriod.java
│ │ │ │ │ ├── MergingMediaSource.java
│ │ │ │ │ ├── ProgressiveMediaPeriod.java
│ │ │ │ │ ├── ProgressiveMediaSource.java
│ │ │ │ │ ├── SampleMetadataQueue.java
│ │ │ │ │ ├── SampleQueue.java
│ │ │ │ │ ├── SampleStream.java
│ │ │ │ │ ├── SequenceableLoader.java
│ │ │ │ │ ├── ShuffleOrder.java
│ │ │ │ │ ├── SilenceMediaSource.java
│ │ │ │ │ ├── SinglePeriodTimeline.java
│ │ │ │ │ ├── SingleSampleMediaPeriod.java
│ │ │ │ │ ├── SingleSampleMediaSource.java
│ │ │ │ │ ├── TrackGroup.java
│ │ │ │ │ ├── TrackGroupArray.java
│ │ │ │ │ ├── UnrecognizedInputFormatException.java
│ │ │ │ │ ├── ads/
│ │ │ │ │ │ ├── AdPlaybackState.java
│ │ │ │ │ │ ├── AdsLoader.java
│ │ │ │ │ │ ├── AdsMediaSource.java
│ │ │ │ │ │ └── SinglePeriodAdTimeline.java
│ │ │ │ │ └── chunk/
│ │ │ │ │ ├── BaseMediaChunk.java
│ │ │ │ │ ├── BaseMediaChunkIterator.java
│ │ │ │ │ ├── BaseMediaChunkOutput.java
│ │ │ │ │ ├── Chunk.java
│ │ │ │ │ ├── ChunkExtractorWrapper.java
│ │ │ │ │ ├── ChunkHolder.java
│ │ │ │ │ ├── ChunkSampleStream.java
│ │ │ │ │ ├── ChunkSource.java
│ │ │ │ │ ├── ContainerMediaChunk.java
│ │ │ │ │ ├── DataChunk.java
│ │ │ │ │ ├── InitializationChunk.java
│ │ │ │ │ ├── MediaChunk.java
│ │ │ │ │ ├── MediaChunkIterator.java
│ │ │ │ │ ├── MediaChunkListIterator.java
│ │ │ │ │ └── SingleSampleMediaChunk.java
│ │ │ │ ├── text/
│ │ │ │ │ ├── CaptionStyleCompat.java
│ │ │ │ │ ├── Cue.java
│ │ │ │ │ ├── SimpleSubtitleDecoder.java
│ │ │ │ │ ├── SimpleSubtitleOutputBuffer.java
│ │ │ │ │ ├── Subtitle.java
│ │ │ │ │ ├── SubtitleDecoder.java
│ │ │ │ │ ├── SubtitleDecoderException.java
│ │ │ │ │ ├── SubtitleDecoderFactory.java
│ │ │ │ │ ├── SubtitleInputBuffer.java
│ │ │ │ │ ├── SubtitleOutputBuffer.java
│ │ │ │ │ ├── TextOutput.java
│ │ │ │ │ ├── TextRenderer.java
│ │ │ │ │ ├── cea/
│ │ │ │ │ │ ├── Cea608Decoder.java
│ │ │ │ │ │ ├── Cea708Cue.java
│ │ │ │ │ │ ├── Cea708Decoder.java
│ │ │ │ │ │ ├── Cea708InitializationData.java
│ │ │ │ │ │ ├── CeaDecoder.java
│ │ │ │ │ │ ├── CeaSubtitle.java
│ │ │ │ │ │ └── CeaUtil.java
│ │ │ │ │ ├── dvb/
│ │ │ │ │ │ ├── DvbDecoder.java
│ │ │ │ │ │ ├── DvbParser.java
│ │ │ │ │ │ └── DvbSubtitle.java
│ │ │ │ │ ├── pgs/
│ │ │ │ │ │ ├── PgsDecoder.java
│ │ │ │ │ │ └── PgsSubtitle.java
│ │ │ │ │ ├── ssa/
│ │ │ │ │ │ ├── SsaDecoder.java
│ │ │ │ │ │ └── SsaSubtitle.java
│ │ │ │ │ ├── subrip/
│ │ │ │ │ │ ├── SubripDecoder.java
│ │ │ │ │ │ └── SubripSubtitle.java
│ │ │ │ │ ├── ttml/
│ │ │ │ │ │ ├── TtmlDecoder.java
│ │ │ │ │ │ ├── TtmlNode.java
│ │ │ │ │ │ ├── TtmlRegion.java
│ │ │ │ │ │ ├── TtmlRenderUtil.java
│ │ │ │ │ │ ├── TtmlStyle.java
│ │ │ │ │ │ └── TtmlSubtitle.java
│ │ │ │ │ ├── tx3g/
│ │ │ │ │ │ ├── Tx3gDecoder.java
│ │ │ │ │ │ └── Tx3gSubtitle.java
│ │ │ │ │ └── webvtt/
│ │ │ │ │ ├── CssParser.java
│ │ │ │ │ ├── Mp4WebvttDecoder.java
│ │ │ │ │ ├── Mp4WebvttSubtitle.java
│ │ │ │ │ ├── WebvttCssStyle.java
│ │ │ │ │ ├── WebvttCue.java
│ │ │ │ │ ├── WebvttCueParser.java
│ │ │ │ │ ├── WebvttDecoder.java
│ │ │ │ │ ├── WebvttParserUtil.java
│ │ │ │ │ └── WebvttSubtitle.java
│ │ │ │ ├── trackselection/
│ │ │ │ │ ├── AdaptiveTrackSelection.java
│ │ │ │ │ ├── BaseTrackSelection.java
│ │ │ │ │ ├── BufferSizeAdaptationBuilder.java
│ │ │ │ │ ├── DefaultTrackSelector.java
│ │ │ │ │ ├── FixedTrackSelection.java
│ │ │ │ │ ├── MappingTrackSelector.java
│ │ │ │ │ ├── RandomTrackSelection.java
│ │ │ │ │ ├── TrackBitrateEstimator.java
│ │ │ │ │ ├── TrackSelection.java
│ │ │ │ │ ├── TrackSelectionArray.java
│ │ │ │ │ ├── TrackSelectionParameters.java
│ │ │ │ │ ├── TrackSelectionUtil.java
│ │ │ │ │ ├── TrackSelector.java
│ │ │ │ │ ├── TrackSelectorResult.java
│ │ │ │ │ └── WindowedTrackBitrateEstimator.java
│ │ │ │ ├── upstream/
│ │ │ │ │ ├── Allocation.java
│ │ │ │ │ ├── Allocator.java
│ │ │ │ │ ├── AssetDataSource.java
│ │ │ │ │ ├── BandwidthMeter.java
│ │ │ │ │ ├── BaseDataSource.java
│ │ │ │ │ ├── ByteArrayDataSink.java
│ │ │ │ │ ├── ByteArrayDataSource.java
│ │ │ │ │ ├── ContentDataSource.java
│ │ │ │ │ ├── DataSchemeDataSource.java
│ │ │ │ │ ├── DataSink.java
│ │ │ │ │ ├── DataSource.java
│ │ │ │ │ ├── DataSourceException.java
│ │ │ │ │ ├── DataSourceInputStream.java
│ │ │ │ │ ├── DataSpec.java
│ │ │ │ │ ├── DefaultAllocator.java
│ │ │ │ │ ├── DefaultBandwidthMeter.java
│ │ │ │ │ ├── DefaultDataSource.java
│ │ │ │ │ ├── DefaultDataSourceFactory.java
│ │ │ │ │ ├── DefaultHttpDataSource.java
│ │ │ │ │ ├── DefaultHttpDataSourceFactory.java
│ │ │ │ │ ├── DefaultLoadErrorHandlingPolicy.java
│ │ │ │ │ ├── DummyDataSource.java
│ │ │ │ │ ├── FileDataSource.java
│ │ │ │ │ ├── FileDataSourceFactory.java
│ │ │ │ │ ├── HttpDataSource.java
│ │ │ │ │ ├── LoadErrorHandlingPolicy.java
│ │ │ │ │ ├── Loader.java
│ │ │ │ │ ├── LoaderErrorThrower.java
│ │ │ │ │ ├── ParsingLoadable.java
│ │ │ │ │ ├── PriorityDataSource.java
│ │ │ │ │ ├── PriorityDataSourceFactory.java
│ │ │ │ │ ├── RawResourceDataSource.java
│ │ │ │ │ ├── ResolvingDataSource.java
│ │ │ │ │ ├── StatsDataSource.java
│ │ │ │ │ ├── TeeDataSource.java
│ │ │ │ │ ├── TransferListener.java
│ │ │ │ │ ├── UdpDataSource.java
│ │ │ │ │ ├── cache/
│ │ │ │ │ │ ├── Cache.java
│ │ │ │ │ │ ├── CacheDataSink.java
│ │ │ │ │ │ ├── CacheDataSinkFactory.java
│ │ │ │ │ │ ├── CacheDataSource.java
│ │ │ │ │ │ ├── CacheDataSourceFactory.java
│ │ │ │ │ │ ├── CacheEvictor.java
│ │ │ │ │ │ ├── CacheFileMetadata.java
│ │ │ │ │ │ ├── CacheFileMetadataIndex.java
│ │ │ │ │ │ ├── CacheKeyFactory.java
│ │ │ │ │ │ ├── CacheSpan.java
│ │ │ │ │ │ ├── CacheUtil.java
│ │ │ │ │ │ ├── CachedContent.java
│ │ │ │ │ │ ├── CachedContentIndex.java
│ │ │ │ │ │ ├── CachedRegionTracker.java
│ │ │ │ │ │ ├── ContentMetadata.java
│ │ │ │ │ │ ├── ContentMetadataMutations.java
│ │ │ │ │ │ ├── DefaultContentMetadata.java
│ │ │ │ │ │ ├── LeastRecentlyUsedCacheEvictor.java
│ │ │ │ │ │ ├── NoOpCacheEvictor.java
│ │ │ │ │ │ ├── SimpleCache.java
│ │ │ │ │ │ └── SimpleCacheSpan.java
│ │ │ │ │ └── crypto/
│ │ │ │ │ ├── AesCipherDataSink.java
│ │ │ │ │ ├── AesCipherDataSource.java
│ │ │ │ │ ├── AesFlushingCipher.java
│ │ │ │ │ └── CryptoUtil.java
│ │ │ │ ├── util/
│ │ │ │ │ ├── AmazonQuirks.java
│ │ │ │ │ ├── Assertions.java
│ │ │ │ │ ├── AtomicFile.java
│ │ │ │ │ ├── Clock.java
│ │ │ │ │ ├── CodecSpecificDataUtil.java
│ │ │ │ │ ├── ColorParser.java
│ │ │ │ │ ├── ConditionVariable.java
│ │ │ │ │ ├── EGLSurfaceTexture.java
│ │ │ │ │ ├── ErrorMessageProvider.java
│ │ │ │ │ ├── EventDispatcher.java
│ │ │ │ │ ├── EventLogger.java
│ │ │ │ │ ├── FlacStreamMetadata.java
│ │ │ │ │ ├── GlUtil.java
│ │ │ │ │ ├── HandlerWrapper.java
│ │ │ │ │ ├── LibraryLoader.java
│ │ │ │ │ ├── Log.java
│ │ │ │ │ ├── Logger.java
│ │ │ │ │ ├── LongArray.java
│ │ │ │ │ ├── MediaClock.java
│ │ │ │ │ ├── MimeTypes.java
│ │ │ │ │ ├── NalUnitUtil.java
│ │ │ │ │ ├── NotificationUtil.java
│ │ │ │ │ ├── ParsableBitArray.java
│ │ │ │ │ ├── ParsableByteArray.java
│ │ │ │ │ ├── ParsableNalUnitBitArray.java
│ │ │ │ │ ├── Predicate.java
│ │ │ │ │ ├── PriorityTaskManager.java
│ │ │ │ │ ├── RepeatModeUtil.java
│ │ │ │ │ ├── ReusableBufferedOutputStream.java
│ │ │ │ │ ├── SlidingPercentile.java
│ │ │ │ │ ├── StandaloneMediaClock.java
│ │ │ │ │ ├── SystemClock.java
│ │ │ │ │ ├── SystemHandlerWrapper.java
│ │ │ │ │ ├── TimedValueQueue.java
│ │ │ │ │ ├── TimestampAdjuster.java
│ │ │ │ │ ├── TraceUtil.java
│ │ │ │ │ ├── UriUtil.java
│ │ │ │ │ ├── Util.java
│ │ │ │ │ └── XmlPullParserUtil.java
│ │ │ │ └── video/
│ │ │ │ ├── AvcConfig.java
│ │ │ │ ├── ColorInfo.java
│ │ │ │ ├── DolbyVisionConfig.java
│ │ │ │ ├── DummySurface.java
│ │ │ │ ├── HevcConfig.java
│ │ │ │ ├── MediaCodecVideoRenderer.java
│ │ │ │ ├── VideoFrameMetadataListener.java
│ │ │ │ ├── VideoFrameReleaseTimeHelper.java
│ │ │ │ ├── VideoListener.java
│ │ │ │ ├── VideoRendererEventListener.java
│ │ │ │ └── spherical/
│ │ │ │ ├── CameraMotionListener.java
│ │ │ │ ├── CameraMotionRenderer.java
│ │ │ │ ├── FrameRotationQueue.java
│ │ │ │ ├── Projection.java
│ │ │ │ └── ProjectionDecoder.java
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── assets/
│ │ │ │ ├── amr/
│ │ │ │ │ ├── sample_nb.amr
│ │ │ │ │ ├── sample_nb.amr.0.dump
│ │ │ │ │ ├── sample_nb_cbr.amr
│ │ │ │ │ ├── sample_nb_cbr.amr.0.dump
│ │ │ │ │ ├── sample_nb_cbr.amr.1.dump
│ │ │ │ │ ├── sample_nb_cbr.amr.2.dump
│ │ │ │ │ ├── sample_nb_cbr.amr.3.dump
│ │ │ │ │ ├── sample_nb_cbr.amr.unklen.dump
│ │ │ │ │ ├── sample_wb.amr
│ │ │ │ │ ├── sample_wb.amr.0.dump
│ │ │ │ │ ├── sample_wb_cbr.amr
│ │ │ │ │ ├── sample_wb_cbr.amr.0.dump
│ │ │ │ │ ├── sample_wb_cbr.amr.1.dump
│ │ │ │ │ ├── sample_wb_cbr.amr.2.dump
│ │ │ │ │ ├── sample_wb_cbr.amr.3.dump
│ │ │ │ │ └── sample_wb_cbr.amr.unklen.dump
│ │ │ │ ├── download-actions/
│ │ │ │ │ ├── dash-download-v0
│ │ │ │ │ ├── dash-remove-v0
│ │ │ │ │ ├── hls-download-v0
│ │ │ │ │ ├── hls-download-v1
│ │ │ │ │ ├── hls-remove-v0
│ │ │ │ │ ├── hls-remove-v1
│ │ │ │ │ ├── progressive-download-v0
│ │ │ │ │ ├── progressive-remove-v0
│ │ │ │ │ ├── ss-download-v0
│ │ │ │ │ ├── ss-download-v1
│ │ │ │ │ ├── ss-remove-v0
│ │ │ │ │ └── ss-remove-v1
│ │ │ │ ├── flv/
│ │ │ │ │ ├── sample.flv
│ │ │ │ │ └── sample.flv.0.dump
│ │ │ │ ├── mkv/
│ │ │ │ │ ├── sample.mkv
│ │ │ │ │ ├── sample.mkv.0.dump
│ │ │ │ │ ├── sample.mkv.1.dump
│ │ │ │ │ ├── sample.mkv.2.dump
│ │ │ │ │ ├── sample.mkv.3.dump
│ │ │ │ │ ├── subsample_encrypted_altref.webm
│ │ │ │ │ ├── subsample_encrypted_altref.webm.0.dump
│ │ │ │ │ ├── subsample_encrypted_noaltref.webm
│ │ │ │ │ └── subsample_encrypted_noaltref.webm.0.dump
│ │ │ │ ├── mp3/
│ │ │ │ │ ├── bear.mp3.0.dump
│ │ │ │ │ ├── bear.mp3.1.dump
│ │ │ │ │ ├── bear.mp3.2.dump
│ │ │ │ │ ├── bear.mp3.3.dump
│ │ │ │ │ ├── play-trimmed.mp3.0.dump
│ │ │ │ │ ├── play-trimmed.mp3.1.dump
│ │ │ │ │ ├── play-trimmed.mp3.2.dump
│ │ │ │ │ ├── play-trimmed.mp3.3.dump
│ │ │ │ │ └── play-trimmed.mp3.unklen.dump
│ │ │ │ ├── mp4/
│ │ │ │ │ ├── sample.mp4.0.dump
│ │ │ │ │ ├── sample.mp4.1.dump
│ │ │ │ │ ├── sample.mp4.2.dump
│ │ │ │ │ ├── sample.mp4.3.dump
│ │ │ │ │ ├── sample_fragmented.mp4.0.dump
│ │ │ │ │ ├── sample_fragmented_seekable.mp4.0.dump
│ │ │ │ │ ├── sample_fragmented_seekable.mp4.1.dump
│ │ │ │ │ ├── sample_fragmented_seekable.mp4.2.dump
│ │ │ │ │ ├── sample_fragmented_seekable.mp4.3.dump
│ │ │ │ │ └── sample_fragmented_sei.mp4.0.dump
│ │ │ │ ├── offline/
│ │ │ │ │ ├── action_file_for_download_index_upgrade.exi
│ │ │ │ │ ├── action_file_incomplete_header.exi
│ │ │ │ │ ├── action_file_no_data.exi
│ │ │ │ │ ├── action_file_one_action.exi
│ │ │ │ │ ├── action_file_two_actions.exi
│ │ │ │ │ ├── action_file_unsupported_version.exi
│ │ │ │ │ └── action_file_zero_actions.exi
│ │ │ │ ├── ogg/
│ │ │ │ │ ├── bear.opus
│ │ │ │ │ ├── bear.opus.0.dump
│ │ │ │ │ ├── bear.opus.1.dump
│ │ │ │ │ ├── bear.opus.2.dump
│ │ │ │ │ ├── bear.opus.3.dump
│ │ │ │ │ ├── bear.opus.unklen.dump
│ │ │ │ │ ├── bear_flac.ogg
│ │ │ │ │ ├── bear_flac.ogg.0.dump
│ │ │ │ │ ├── bear_flac.ogg.1.dump
│ │ │ │ │ ├── bear_flac.ogg.2.dump
│ │ │ │ │ ├── bear_flac.ogg.3.dump
│ │ │ │ │ ├── bear_flac.ogg.unklen.dump
│ │ │ │ │ ├── bear_flac_noseektable.ogg
│ │ │ │ │ ├── bear_flac_noseektable.ogg.0.dump
│ │ │ │ │ ├── bear_flac_noseektable.ogg.1.dump
│ │ │ │ │ ├── bear_flac_noseektable.ogg.2.dump
│ │ │ │ │ ├── bear_flac_noseektable.ogg.3.dump
│ │ │ │ │ ├── bear_flac_noseektable.ogg.unklen.dump
│ │ │ │ │ ├── bear_vorbis.ogg
│ │ │ │ │ ├── bear_vorbis.ogg.0.dump
│ │ │ │ │ ├── bear_vorbis.ogg.1.dump
│ │ │ │ │ ├── bear_vorbis.ogg.2.dump
│ │ │ │ │ ├── bear_vorbis.ogg.3.dump
│ │ │ │ │ └── bear_vorbis.ogg.unklen.dump
│ │ │ │ ├── rawcc/
│ │ │ │ │ ├── sample.rawcc
│ │ │ │ │ └── sample.rawcc.0.dump
│ │ │ │ ├── ssa/
│ │ │ │ │ ├── empty
│ │ │ │ │ ├── invalid_timecodes
│ │ │ │ │ ├── no_end_timecodes
│ │ │ │ │ ├── typical
│ │ │ │ │ ├── typical_dialogue
│ │ │ │ │ ├── typical_format
│ │ │ │ │ └── typical_header
│ │ │ │ ├── subrip/
│ │ │ │ │ ├── empty
│ │ │ │ │ ├── no_end_timecodes
│ │ │ │ │ ├── typical
│ │ │ │ │ ├── typical_extra_blank_line
│ │ │ │ │ ├── typical_missing_sequence
│ │ │ │ │ ├── typical_missing_timecode
│ │ │ │ │ ├── typical_negative_timestamps
│ │ │ │ │ ├── typical_unexpected_end
│ │ │ │ │ ├── typical_with_byte_order_mark
│ │ │ │ │ └── typical_with_tags
│ │ │ │ ├── ts/
│ │ │ │ │ ├── bbb_2500ms.ts
│ │ │ │ │ ├── elephants_dream.mpg
│ │ │ │ │ ├── sample.ac3
│ │ │ │ │ ├── sample.ac3.0.dump
│ │ │ │ │ ├── sample.ac4
│ │ │ │ │ ├── sample.ac4.0.dump
│ │ │ │ │ ├── sample.adts
│ │ │ │ │ ├── sample.adts.0.dump
│ │ │ │ │ ├── sample.eac3
│ │ │ │ │ ├── sample.eac3.0.dump
│ │ │ │ │ ├── sample.ps
│ │ │ │ │ ├── sample.ps.0.dump
│ │ │ │ │ ├── sample.ps.1.dump
│ │ │ │ │ ├── sample.ps.2.dump
│ │ │ │ │ ├── sample.ps.3.dump
│ │ │ │ │ ├── sample.ps.unklen.dump
│ │ │ │ │ ├── sample.ts
│ │ │ │ │ ├── sample.ts.0.dump
│ │ │ │ │ ├── sample.ts.1.dump
│ │ │ │ │ ├── sample.ts.2.dump
│ │ │ │ │ ├── sample.ts.3.dump
│ │ │ │ │ ├── sample.ts.unklen.dump
│ │ │ │ │ ├── sample_cbs.adts
│ │ │ │ │ ├── sample_cbs.adts.0.dump
│ │ │ │ │ ├── sample_cbs.adts.1.dump
│ │ │ │ │ ├── sample_cbs.adts.2.dump
│ │ │ │ │ ├── sample_cbs.adts.3.dump
│ │ │ │ │ ├── sample_cbs.adts.unklen.dump
│ │ │ │ │ └── sample_with_sdt.ts
│ │ │ │ ├── ttml/
│ │ │ │ │ ├── bitmap_percentage_region.xml
│ │ │ │ │ ├── bitmap_pixel_region.xml
│ │ │ │ │ ├── bitmap_unsupported_region.xml
│ │ │ │ │ ├── chain_multiple_styles.xml
│ │ │ │ │ ├── font_size.xml
│ │ │ │ │ ├── font_size_empty.xml
│ │ │ │ │ ├── font_size_invalid.xml
│ │ │ │ │ ├── font_size_no_unit.xml
│ │ │ │ │ ├── frame_rate.xml
│ │ │ │ │ ├── inherit_and_override_style.xml
│ │ │ │ │ ├── inherit_global_and_parent.xml
│ │ │ │ │ ├── inherit_multiple_styles.xml
│ │ │ │ │ ├── inherit_style.xml
│ │ │ │ │ ├── inline_style_attributes.xml
│ │ │ │ │ ├── multiple_regions.xml
│ │ │ │ │ └── no_underline_linethrough.xml
│ │ │ │ ├── tx3g/
│ │ │ │ │ ├── initialization
│ │ │ │ │ ├── initialization_all_defaults
│ │ │ │ │ ├── no_subtitle
│ │ │ │ │ ├── sample_just_text
│ │ │ │ │ ├── sample_utf16_be_no_styl
│ │ │ │ │ ├── sample_utf16_le_no_styl
│ │ │ │ │ ├── sample_with_multiple_styl
│ │ │ │ │ ├── sample_with_other_extension
│ │ │ │ │ ├── sample_with_styl
│ │ │ │ │ ├── sample_with_styl_all_defaults
│ │ │ │ │ └── sample_with_tbox
│ │ │ │ ├── wav/
│ │ │ │ │ ├── sample.wav.0.dump
│ │ │ │ │ ├── sample.wav.1.dump
│ │ │ │ │ ├── sample.wav.2.dump
│ │ │ │ │ └── sample.wav.3.dump
│ │ │ │ ├── webm/
│ │ │ │ │ └── vorbis_codec_private
│ │ │ │ └── webvtt/
│ │ │ │ ├── empty
│ │ │ │ ├── typical
│ │ │ │ ├── typical_with_bad_timestamps
│ │ │ │ ├── typical_with_comments
│ │ │ │ ├── typical_with_identifiers
│ │ │ │ ├── with_bad_cue_header
│ │ │ │ ├── with_bom
│ │ │ │ ├── with_css_complex_selectors
│ │ │ │ ├── with_css_styles
│ │ │ │ ├── with_positioning
│ │ │ │ └── with_tags
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ ├── CTest.java
│ │ │ ├── DefaultLoadControlTest.java
│ │ │ ├── DefaultMediaClockTest.java
│ │ │ ├── ExoPlayerTest.java
│ │ │ ├── FormatTest.java
│ │ │ ├── MediaPeriodQueueTest.java
│ │ │ ├── TimelineTest.java
│ │ │ ├── analytics/
│ │ │ │ └── AnalyticsCollectorTest.java
│ │ │ ├── audio/
│ │ │ │ ├── Ac3UtilTest.java
│ │ │ │ ├── AudioFocusManagerTest.java
│ │ │ │ ├── DefaultAudioSinkTest.java
│ │ │ │ ├── SilenceSkippingAudioProcessorTest.java
│ │ │ │ ├── SimpleDecoderAudioRendererTest.java
│ │ │ │ └── SonicAudioProcessorTest.java
│ │ │ ├── database/
│ │ │ │ └── VersionTableTest.java
│ │ │ ├── drm/
│ │ │ │ ├── ClearKeyUtilTest.java
│ │ │ │ ├── DrmInitDataTest.java
│ │ │ │ └── OfflineLicenseHelperTest.java
│ │ │ ├── extractor/
│ │ │ │ ├── ConstantBitrateSeekMapTest.java
│ │ │ │ ├── DefaultExtractorInputTest.java
│ │ │ │ ├── DefaultExtractorsFactoryTest.java
│ │ │ │ ├── ExtractorTest.java
│ │ │ │ ├── Id3PeekerTest.java
│ │ │ │ ├── amr/
│ │ │ │ │ ├── AmrExtractorSeekTest.java
│ │ │ │ │ └── AmrExtractorTest.java
│ │ │ │ ├── flv/
│ │ │ │ │ └── FlvExtractorTest.java
│ │ │ │ ├── mkv/
│ │ │ │ │ ├── DefaultEbmlReaderTest.java
│ │ │ │ │ ├── MatroskaExtractorTest.java
│ │ │ │ │ └── VarintReaderTest.java
│ │ │ │ ├── mp3/
│ │ │ │ │ ├── Mp3ExtractorTest.java
│ │ │ │ │ └── XingSeekerTest.java
│ │ │ │ ├── mp4/
│ │ │ │ │ ├── AtomParsersTest.java
│ │ │ │ │ ├── FragmentedMp4ExtractorTest.java
│ │ │ │ │ ├── MdtaMetadataEntryTest.java
│ │ │ │ │ ├── Mp4ExtractorTest.java
│ │ │ │ │ └── PsshAtomUtilTest.java
│ │ │ │ ├── ogg/
│ │ │ │ │ ├── DefaultOggSeekerTest.java
│ │ │ │ │ ├── OggExtractorTest.java
│ │ │ │ │ ├── OggPacketTest.java
│ │ │ │ │ ├── OggPageHeaderTest.java
│ │ │ │ │ ├── OggTestFile.java
│ │ │ │ │ ├── VorbisBitArrayTest.java
│ │ │ │ │ ├── VorbisReaderTest.java
│ │ │ │ │ └── VorbisUtilTest.java
│ │ │ │ ├── rawcc/
│ │ │ │ │ └── RawCcExtractorTest.java
│ │ │ │ ├── ts/
│ │ │ │ │ ├── Ac3ExtractorTest.java
│ │ │ │ │ ├── Ac4ExtractorTest.java
│ │ │ │ │ ├── AdtsExtractorSeekTest.java
│ │ │ │ │ ├── AdtsExtractorTest.java
│ │ │ │ │ ├── AdtsReaderTest.java
│ │ │ │ │ ├── PsDurationReaderTest.java
│ │ │ │ │ ├── PsExtractorSeekTest.java
│ │ │ │ │ ├── PsExtractorTest.java
│ │ │ │ │ ├── SectionReaderTest.java
│ │ │ │ │ ├── TsDurationReaderTest.java
│ │ │ │ │ ├── TsExtractorSeekTest.java
│ │ │ │ │ └── TsExtractorTest.java
│ │ │ │ └── wav/
│ │ │ │ └── WavExtractorTest.java
│ │ │ ├── metadata/
│ │ │ │ ├── MetadataRendererTest.java
│ │ │ │ ├── emsg/
│ │ │ │ │ ├── EventMessageDecoderTest.java
│ │ │ │ │ ├── EventMessageEncoderTest.java
│ │ │ │ │ └── EventMessageTest.java
│ │ │ │ ├── flac/
│ │ │ │ │ ├── PictureFrameTest.java
│ │ │ │ │ └── VorbisCommentTest.java
│ │ │ │ ├── icy/
│ │ │ │ │ ├── IcyDecoderTest.java
│ │ │ │ │ ├── IcyHeadersTest.java
│ │ │ │ │ └── IcyInfoTest.java
│ │ │ │ ├── id3/
│ │ │ │ │ ├── ChapterFrameTest.java
│ │ │ │ │ ├── ChapterTocFrameTest.java
│ │ │ │ │ ├── Id3DecoderTest.java
│ │ │ │ │ └── MlltFrameTest.java
│ │ │ │ └── scte35/
│ │ │ │ └── SpliceInfoDecoderTest.java
│ │ │ ├── offline/
│ │ │ │ ├── ActionFileTest.java
│ │ │ │ ├── ActionFileUpgradeUtilTest.java
│ │ │ │ ├── DefaultDownloadIndexTest.java
│ │ │ │ ├── DefaultDownloaderFactoryTest.java
│ │ │ │ ├── DownloadBuilder.java
│ │ │ │ ├── DownloadHelperTest.java
│ │ │ │ ├── DownloadManagerTest.java
│ │ │ │ ├── DownloadRequestTest.java
│ │ │ │ └── StreamKeyTest.java
│ │ │ ├── source/
│ │ │ │ ├── ClippingMediaSourceTest.java
│ │ │ │ ├── CompositeSequenceableLoaderTest.java
│ │ │ │ ├── ConcatenatingMediaSourceTest.java
│ │ │ │ ├── LoopingMediaSourceTest.java
│ │ │ │ ├── MergingMediaSourceTest.java
│ │ │ │ ├── SampleQueueTest.java
│ │ │ │ ├── ShuffleOrderTest.java
│ │ │ │ ├── SinglePeriodTimelineTest.java
│ │ │ │ ├── TrackGroupArrayTest.java
│ │ │ │ ├── TrackGroupTest.java
│ │ │ │ ├── ads/
│ │ │ │ │ └── AdPlaybackStateTest.java
│ │ │ │ └── chunk/
│ │ │ │ └── MediaChunkListIteratorTest.java
│ │ │ ├── text/
│ │ │ │ ├── ssa/
│ │ │ │ │ └── SsaDecoderTest.java
│ │ │ │ ├── subrip/
│ │ │ │ │ └── SubripDecoderTest.java
│ │ │ │ ├── ttml/
│ │ │ │ │ ├── TtmlDecoderTest.java
│ │ │ │ │ ├── TtmlRenderUtilTest.java
│ │ │ │ │ └── TtmlStyleTest.java
│ │ │ │ ├── tx3g/
│ │ │ │ │ └── Tx3gDecoderTest.java
│ │ │ │ └── webvtt/
│ │ │ │ ├── CssParserTest.java
│ │ │ │ ├── Mp4WebvttDecoderTest.java
│ │ │ │ ├── WebvttCueParserTest.java
│ │ │ │ ├── WebvttDecoderTest.java
│ │ │ │ └── WebvttSubtitleTest.java
│ │ │ ├── trackselection/
│ │ │ │ ├── AdaptiveTrackSelectionTest.java
│ │ │ │ ├── BufferSizeAdaptiveTrackSelectionTest.java
│ │ │ │ ├── DefaultTrackSelectorTest.java
│ │ │ │ ├── MappingTrackSelectorTest.java
│ │ │ │ ├── TrackSelectionUtilTest.java
│ │ │ │ ├── TrackSelectorTest.java
│ │ │ │ └── WindowedTrackBitrateEstimatorTest.java
│ │ │ ├── upstream/
│ │ │ │ ├── AssetDataSourceTest.java
│ │ │ │ ├── BaseDataSourceTest.java
│ │ │ │ ├── ByteArrayDataSourceTest.java
│ │ │ │ ├── DataSchemeDataSourceTest.java
│ │ │ │ ├── DataSourceAsserts.java
│ │ │ │ ├── DataSourceInputStreamTest.java
│ │ │ │ ├── DataSpecTest.java
│ │ │ │ ├── DefaultBandwidthMeterTest.java
│ │ │ │ ├── DefaultLoadErrorHandlingPolicyTest.java
│ │ │ │ ├── cache/
│ │ │ │ │ ├── CacheDataSourceTest.java
│ │ │ │ │ ├── CacheDataSourceTest2.java
│ │ │ │ │ ├── CacheUtilTest.java
│ │ │ │ │ ├── CachedContentIndexTest.java
│ │ │ │ │ ├── CachedRegionTrackerTest.java
│ │ │ │ │ ├── DefaultContentMetadataTest.java
│ │ │ │ │ ├── LeastRecentlyUsedCacheEvictorTest.java
│ │ │ │ │ ├── SimpleCacheSpanTest.java
│ │ │ │ │ └── SimpleCacheTest.java
│ │ │ │ └── crypto/
│ │ │ │ └── AesFlushingCipherTest.java
│ │ │ ├── util/
│ │ │ │ ├── AtomicFileTest.java
│ │ │ │ ├── ColorParserTest.java
│ │ │ │ ├── FlacStreamMetadataTest.java
│ │ │ │ ├── MimeTypesTest.java
│ │ │ │ ├── NalUnitUtilTest.java
│ │ │ │ ├── ParsableBitArrayTest.java
│ │ │ │ ├── ParsableByteArrayTest.java
│ │ │ │ ├── ParsableNalUnitBitArrayTest.java
│ │ │ │ ├── ReusableBufferedOutputStreamTest.java
│ │ │ │ ├── TimedValueQueueTest.java
│ │ │ │ ├── UriUtilTest.java
│ │ │ │ └── UtilTest.java
│ │ │ └── video/
│ │ │ └── spherical/
│ │ │ ├── FrameRotationQueueTest.java
│ │ │ ├── ProjectionDecoderTest.java
│ │ │ └── ProjectionTest.java
│ │ ├── dash/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── source/
│ │ │ │ └── dash/
│ │ │ │ ├── DashChunkSource.java
│ │ │ │ ├── DashManifestStaleException.java
│ │ │ │ ├── DashMediaPeriod.java
│ │ │ │ ├── DashMediaSource.java
│ │ │ │ ├── DashSegmentIndex.java
│ │ │ │ ├── DashUtil.java
│ │ │ │ ├── DashWrappingSegmentIndex.java
│ │ │ │ ├── DefaultDashChunkSource.java
│ │ │ │ ├── EventSampleStream.java
│ │ │ │ ├── PlayerEmsgHandler.java
│ │ │ │ ├── manifest/
│ │ │ │ │ ├── AdaptationSet.java
│ │ │ │ │ ├── DashManifest.java
│ │ │ │ │ ├── DashManifestParser.java
│ │ │ │ │ ├── DashManifestParser2.java
│ │ │ │ │ ├── Descriptor.java
│ │ │ │ │ ├── EventStream.java
│ │ │ │ │ ├── Period.java
│ │ │ │ │ ├── ProgramInformation.java
│ │ │ │ │ ├── RangedUri.java
│ │ │ │ │ ├── Representation.java
│ │ │ │ │ ├── SegmentBase.java
│ │ │ │ │ ├── SingleSegmentIndex.java
│ │ │ │ │ ├── UrlTemplate.java
│ │ │ │ │ └── UtcTimingElement.java
│ │ │ │ └── offline/
│ │ │ │ └── DashDownloader.java
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── assets/
│ │ │ │ ├── sample_mpd
│ │ │ │ ├── sample_mpd_event_stream
│ │ │ │ ├── sample_mpd_labels
│ │ │ │ ├── sample_mpd_segment_template
│ │ │ │ └── sample_mpd_unknown_mime_type
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── source/
│ │ │ └── dash/
│ │ │ ├── DashMediaPeriodTest.java
│ │ │ ├── DashMediaSourceTest.java
│ │ │ ├── DashUtilTest.java
│ │ │ ├── EventSampleStreamTest.java
│ │ │ ├── manifest/
│ │ │ │ ├── DashManifestParserTest.java
│ │ │ │ ├── DashManifestTest.java
│ │ │ │ ├── RangedUriTest.java
│ │ │ │ └── UrlTemplateTest.java
│ │ │ └── offline/
│ │ │ ├── DashDownloadTestData.java
│ │ │ ├── DashDownloaderTest.java
│ │ │ ├── DownloadHelperTest.java
│ │ │ ├── DownloadManagerDashTest.java
│ │ │ └── DownloadServiceDashTest.java
│ │ ├── hls/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── source/
│ │ │ │ └── hls/
│ │ │ │ ├── Aes128DataSource.java
│ │ │ │ ├── DefaultHlsDataSourceFactory.java
│ │ │ │ ├── DefaultHlsExtractorFactory.java
│ │ │ │ ├── HlsChunkSource.java
│ │ │ │ ├── HlsDataSourceFactory.java
│ │ │ │ ├── HlsExtractorFactory.java
│ │ │ │ ├── HlsManifest.java
│ │ │ │ ├── HlsMediaChunk.java
│ │ │ │ ├── HlsMediaPeriod.java
│ │ │ │ ├── HlsMediaSource.java
│ │ │ │ ├── HlsMetadataType.java
│ │ │ │ ├── HlsSampleStream.java
│ │ │ │ ├── HlsSampleStreamWrapper.java
│ │ │ │ ├── HlsTrackMetadataEntry.java
│ │ │ │ ├── SampleQueueMappingException.java
│ │ │ │ ├── TimestampAdjusterProvider.java
│ │ │ │ ├── WebvttExtractor.java
│ │ │ │ ├── offline/
│ │ │ │ │ └── HlsDownloader.java
│ │ │ │ └── playlist/
│ │ │ │ ├── DefaultHlsPlaylistParserFactory.java
│ │ │ │ ├── DefaultHlsPlaylistTracker.java
│ │ │ │ ├── FilteringHlsPlaylistParserFactory.java
│ │ │ │ ├── HlsMasterPlaylist.java
│ │ │ │ ├── HlsMediaPlaylist.java
│ │ │ │ ├── HlsPlaylist.java
│ │ │ │ ├── HlsPlaylistParser.java
│ │ │ │ ├── HlsPlaylistParserFactory.java
│ │ │ │ └── HlsPlaylistTracker.java
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── source/
│ │ │ └── hls/
│ │ │ ├── Aes128DataSourceTest.java
│ │ │ ├── HlsMediaPeriodTest.java
│ │ │ ├── WebvttExtractorTest.java
│ │ │ ├── offline/
│ │ │ │ ├── DownloadHelperTest.java
│ │ │ │ ├── HlsDownloadTestData.java
│ │ │ │ └── HlsDownloaderTest.java
│ │ │ └── playlist/
│ │ │ ├── HlsMasterPlaylistParserTest.java
│ │ │ └── HlsMediaPlaylistParserTest.java
│ │ ├── sabr/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── source/
│ │ │ │ └── sabr/
│ │ │ │ ├── DefaultSabrChunkSource.java
│ │ │ │ ├── EventSampleStream.java
│ │ │ │ ├── PlayerEmsgHandler.java
│ │ │ │ ├── SabrChunkSource.java
│ │ │ │ ├── SabrMediaPeriod.java
│ │ │ │ ├── SabrMediaSource.java
│ │ │ │ ├── SabrSegmentIndex.java
│ │ │ │ ├── SabrWrappingSegmentIndex.java
│ │ │ │ ├── manifest/
│ │ │ │ │ ├── AdaptationSet.java
│ │ │ │ │ ├── EventStream.java
│ │ │ │ │ ├── Period.java
│ │ │ │ │ ├── RangedUri.java
│ │ │ │ │ ├── Representation.java
│ │ │ │ │ ├── SabrManifest.java
│ │ │ │ │ ├── SabrManifestParser.java
│ │ │ │ │ ├── SegmentBase.java
│ │ │ │ │ ├── SingleSegmentIndex.java
│ │ │ │ │ └── UrlTemplate.java
│ │ │ │ └── parser/
│ │ │ │ ├── SabrProcessor.java
│ │ │ │ ├── SabrStream.java
│ │ │ │ ├── adapter/
│ │ │ │ │ ├── SabrFragmentedMp4Adapter.java
│ │ │ │ │ └── SabrMatroskaAdapter.java
│ │ │ │ ├── exceptions/
│ │ │ │ │ ├── MediaSegmentMismatchError.java
│ │ │ │ │ ├── PoTokenError.java
│ │ │ │ │ ├── SabrStreamConsumedError.java
│ │ │ │ │ └── SabrStreamError.java
│ │ │ │ ├── frames/
│ │ │ │ │ ├── AACFrameExtractor.java
│ │ │ │ │ ├── AVCFrameExtractor.java
│ │ │ │ │ ├── BaseFrameExtractor.java
│ │ │ │ │ ├── FrameExtractor.java
│ │ │ │ │ ├── OpusFrameExtractor.java
│ │ │ │ │ ├── VP9FrameExtractor.java
│ │ │ │ │ └── VorbisFrameExtractor.java
│ │ │ │ ├── misc/
│ │ │ │ │ ├── EnabledTrackTypes.java
│ │ │ │ │ ├── SabrExtractorInput.java
│ │ │ │ │ └── Utils.java
│ │ │ │ ├── models/
│ │ │ │ │ ├── AudioSelector.java
│ │ │ │ │ ├── CaptionSelector.java
│ │ │ │ │ ├── ConsumedRange.java
│ │ │ │ │ ├── FormatSelector.java
│ │ │ │ │ ├── Segment.java
│ │ │ │ │ ├── SelectedFormat.java
│ │ │ │ │ └── VideoSelector.java
│ │ │ │ ├── parts/
│ │ │ │ │ ├── FormatInitializedSabrPart.java
│ │ │ │ │ ├── MediaSeekSabrPart.java
│ │ │ │ │ ├── MediaSegmentDataSabrPart.java
│ │ │ │ │ ├── MediaSegmentEndSabrPart.java
│ │ │ │ │ ├── MediaSegmentInitSabrPart.java
│ │ │ │ │ ├── PoTokenStatusSabrPart.java
│ │ │ │ │ ├── RefreshPlayerResponseSabrPart.java
│ │ │ │ │ └── SabrPart.java
│ │ │ │ ├── results/
│ │ │ │ │ ├── ProcessFormatInitializationMetadataResult.java
│ │ │ │ │ ├── ProcessLiveMetadataResult.java
│ │ │ │ │ ├── ProcessMediaEndResult.java
│ │ │ │ │ ├── ProcessMediaHeaderResult.java
│ │ │ │ │ ├── ProcessMediaResult.java
│ │ │ │ │ ├── ProcessSabrSeekResult.java
│ │ │ │ │ └── ProcessStreamProtectionStatusResult.java
│ │ │ │ └── ump/
│ │ │ │ ├── UMPDecoder.java
│ │ │ │ ├── UMPEncoder.java
│ │ │ │ ├── UMPInputStream.java
│ │ │ │ ├── UMPPart.java
│ │ │ │ └── UMPPartId.java
│ │ │ └── proto/
│ │ │ └── sabr/
│ │ │ ├── misc/
│ │ │ │ └── common.proto
│ │ │ ├── other/
│ │ │ │ └── ump_part_id.proto
│ │ │ └── videostreaming/
│ │ │ ├── buffered_range.proto
│ │ │ ├── client_abr_state.proto
│ │ │ ├── crypto_params.proto
│ │ │ ├── format_initialization_metadata.proto
│ │ │ ├── innertube_request.proto
│ │ │ ├── live_metadata.proto
│ │ │ ├── media_capabilities.proto
│ │ │ ├── media_header.proto
│ │ │ ├── next_request_policy.proto
│ │ │ ├── onesie_header.proto
│ │ │ ├── onesie_header_type.proto
│ │ │ ├── onesie_innertube_request.proto
│ │ │ ├── onesie_innertube_response.proto
│ │ │ ├── onesie_proxy_status.proto
│ │ │ ├── onesie_request.proto
│ │ │ ├── playback_cookie.proto
│ │ │ ├── reload_player_response.proto
│ │ │ ├── sabr_context_sending_policy.proto
│ │ │ ├── sabr_context_update.proto
│ │ │ ├── sabr_error.proto
│ │ │ ├── sabr_redirect.proto
│ │ │ ├── sabr_seek.proto
│ │ │ ├── stream_protection_status.proto
│ │ │ ├── streamer_context.proto
│ │ │ ├── time_range.proto
│ │ │ └── video_playback_abr_request.proto
│ │ ├── smoothstreaming/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── source/
│ │ │ │ └── smoothstreaming/
│ │ │ │ ├── DefaultSsChunkSource.java
│ │ │ │ ├── SsChunkSource.java
│ │ │ │ ├── SsMediaPeriod.java
│ │ │ │ ├── SsMediaSource.java
│ │ │ │ ├── manifest/
│ │ │ │ │ ├── SsManifest.java
│ │ │ │ │ ├── SsManifestParser.java
│ │ │ │ │ └── SsUtil.java
│ │ │ │ └── offline/
│ │ │ │ └── SsDownloader.java
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── assets/
│ │ │ │ ├── sample_ismc_1
│ │ │ │ └── sample_ismc_2
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── source/
│ │ │ └── smoothstreaming/
│ │ │ ├── SsMediaPeriodTest.java
│ │ │ ├── SsTestUtils.java
│ │ │ ├── manifest/
│ │ │ │ ├── SsManifestParserTest.java
│ │ │ │ └── SsManifestTest.java
│ │ │ └── offline/
│ │ │ ├── DownloadHelperTest.java
│ │ │ └── SsDownloaderTest.java
│ │ └── ui/
│ │ ├── README.md
│ │ ├── build.gradle
│ │ └── src/
│ │ ├── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── ui/
│ │ │ │ ├── AspectRatioFrameLayout.java
│ │ │ │ ├── DebugTextViewHelper.java
│ │ │ │ ├── DefaultTimeBar.java
│ │ │ │ ├── DefaultTrackNameProvider.java
│ │ │ │ ├── DownloadNotificationHelper.java
│ │ │ │ ├── DownloadNotificationUtil.java
│ │ │ │ ├── PlaybackControlView.java
│ │ │ │ ├── PlayerControlView.java
│ │ │ │ ├── PlayerNotificationManager.java
│ │ │ │ ├── PlayerView.java
│ │ │ │ ├── SimpleExoPlayerView.java
│ │ │ │ ├── SubtitlePainter.java
│ │ │ │ ├── SubtitleView.java
│ │ │ │ ├── TimeBar.java
│ │ │ │ ├── TrackNameProvider.java
│ │ │ │ ├── TrackSelectionDialogBuilder.java
│ │ │ │ ├── TrackSelectionView.java
│ │ │ │ └── spherical/
│ │ │ │ ├── CanvasRenderer.java
│ │ │ │ ├── GlViewGroup.java
│ │ │ │ ├── OrientationListener.java
│ │ │ │ ├── PointerRenderer.java
│ │ │ │ ├── ProjectionRenderer.java
│ │ │ │ ├── SceneRenderer.java
│ │ │ │ ├── SingleTapListener.java
│ │ │ │ ├── SphericalSurfaceView.java
│ │ │ │ └── TouchTracker.java
│ │ │ └── res/
│ │ │ ├── drawable/
│ │ │ │ └── exo_edit_mode_logo.xml
│ │ │ ├── drawable-anydpi-v21/
│ │ │ │ ├── exo_controls_fullscreen_enter.xml
│ │ │ │ ├── exo_controls_fullscreen_exit.xml
│ │ │ │ ├── exo_controls_repeat_all.xml
│ │ │ │ ├── exo_controls_repeat_off.xml
│ │ │ │ ├── exo_controls_repeat_one.xml
│ │ │ │ ├── exo_controls_shuffle_off.xml
│ │ │ │ ├── exo_controls_shuffle_on.xml
│ │ │ │ ├── exo_icon_fastforward.xml
│ │ │ │ ├── exo_icon_next.xml
│ │ │ │ ├── exo_icon_pause.xml
│ │ │ │ ├── exo_icon_play.xml
│ │ │ │ ├── exo_icon_previous.xml
│ │ │ │ ├── exo_icon_rewind.xml
│ │ │ │ └── exo_icon_stop.xml
│ │ │ ├── layout/
│ │ │ │ ├── exo_list_divider.xml
│ │ │ │ ├── exo_playback_control_view.xml
│ │ │ │ ├── exo_player_control_view.xml
│ │ │ │ ├── exo_player_view.xml
│ │ │ │ ├── exo_simple_player_view.xml
│ │ │ │ └── exo_track_selection_dialog.xml
│ │ │ ├── values/
│ │ │ │ ├── attrs.xml
│ │ │ │ ├── constants.xml
│ │ │ │ ├── drawables.xml
│ │ │ │ ├── ids.xml
│ │ │ │ ├── strings.xml
│ │ │ │ └── styles.xml
│ │ │ ├── values-af/
│ │ │ │ └── strings.xml
│ │ │ ├── values-am/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ar/
│ │ │ │ └── strings.xml
│ │ │ ├── values-az/
│ │ │ │ └── strings.xml
│ │ │ ├── values-b+sr+Latn/
│ │ │ │ └── strings.xml
│ │ │ ├── values-be/
│ │ │ │ └── strings.xml
│ │ │ ├── values-bg/
│ │ │ │ └── strings.xml
│ │ │ ├── values-bn/
│ │ │ │ └── strings.xml
│ │ │ ├── values-bs/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ca/
│ │ │ │ └── strings.xml
│ │ │ ├── values-cs/
│ │ │ │ └── strings.xml
│ │ │ ├── values-da/
│ │ │ │ └── strings.xml
│ │ │ ├── values-de/
│ │ │ │ └── strings.xml
│ │ │ ├── values-el/
│ │ │ │ └── strings.xml
│ │ │ ├── values-en-rAU/
│ │ │ │ └── strings.xml
│ │ │ ├── values-en-rGB/
│ │ │ │ └── strings.xml
│ │ │ ├── values-en-rIN/
│ │ │ │ └── strings.xml
│ │ │ ├── values-es/
│ │ │ │ └── strings.xml
│ │ │ ├── values-es-rUS/
│ │ │ │ └── strings.xml
│ │ │ ├── values-et/
│ │ │ │ └── strings.xml
│ │ │ ├── values-eu/
│ │ │ │ └── strings.xml
│ │ │ ├── values-fa/
│ │ │ │ └── strings.xml
│ │ │ ├── values-fi/
│ │ │ │ └── strings.xml
│ │ │ ├── values-fr/
│ │ │ │ └── strings.xml
│ │ │ ├── values-fr-rCA/
│ │ │ │ └── strings.xml
│ │ │ ├── values-gl/
│ │ │ │ └── strings.xml
│ │ │ ├── values-gu/
│ │ │ │ └── strings.xml
│ │ │ ├── values-hi/
│ │ │ │ └── strings.xml
│ │ │ ├── values-hr/
│ │ │ │ └── strings.xml
│ │ │ ├── values-hu/
│ │ │ │ └── strings.xml
│ │ │ ├── values-hy/
│ │ │ │ └── strings.xml
│ │ │ ├── values-in/
│ │ │ │ └── strings.xml
│ │ │ ├── values-is/
│ │ │ │ └── strings.xml
│ │ │ ├── values-it/
│ │ │ │ └── strings.xml
│ │ │ ├── values-iw/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ja/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ka/
│ │ │ │ └── strings.xml
│ │ │ ├── values-kk/
│ │ │ │ └── strings.xml
│ │ │ ├── values-km/
│ │ │ │ └── strings.xml
│ │ │ ├── values-kn/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ko/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ky/
│ │ │ │ └── strings.xml
│ │ │ ├── values-lo/
│ │ │ │ └── strings.xml
│ │ │ ├── values-lt/
│ │ │ │ └── strings.xml
│ │ │ ├── values-lv/
│ │ │ │ └── strings.xml
│ │ │ ├── values-mk/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ml/
│ │ │ │ └── strings.xml
│ │ │ ├── values-mn/
│ │ │ │ └── strings.xml
│ │ │ ├── values-mr/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ms/
│ │ │ │ └── strings.xml
│ │ │ ├── values-my/
│ │ │ │ └── strings.xml
│ │ │ ├── values-nb/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ne/
│ │ │ │ └── strings.xml
│ │ │ ├── values-nl/
│ │ │ │ └── strings.xml
│ │ │ ├── values-pa/
│ │ │ │ └── strings.xml
│ │ │ ├── values-pl/
│ │ │ │ └── strings.xml
│ │ │ ├── values-pt/
│ │ │ │ └── strings.xml
│ │ │ ├── values-pt-rPT/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ro/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ru/
│ │ │ │ └── strings.xml
│ │ │ ├── values-si/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sk/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sl/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sq/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sr/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sv/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sw/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ta/
│ │ │ │ └── strings.xml
│ │ │ ├── values-te/
│ │ │ │ └── strings.xml
│ │ │ ├── values-th/
│ │ │ │ └── strings.xml
│ │ │ ├── values-tl/
│ │ │ │ └── strings.xml
│ │ │ ├── values-tr/
│ │ │ │ └── strings.xml
│ │ │ ├── values-uk/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ur/
│ │ │ │ └── strings.xml
│ │ │ ├── values-uz/
│ │ │ │ └── strings.xml
│ │ │ ├── values-vi/
│ │ │ │ └── strings.xml
│ │ │ ├── values-zh-rCN/
│ │ │ │ └── strings.xml
│ │ │ ├── values-zh-rHK/
│ │ │ │ └── strings.xml
│ │ │ ├── values-zh-rTW/
│ │ │ │ └── strings.xml
│ │ │ └── values-zu/
│ │ │ └── strings.xml
│ │ └── test/
│ │ ├── AndroidManifest.xml
│ │ └── java/
│ │ └── com/
│ │ └── google/
│ │ └── android/
│ │ └── exoplayer2/
│ │ └── ui/
│ │ └── spherical/
│ │ ├── CanvasRendererTest.java
│ │ └── TouchTrackerTest.java
│ ├── playbacktests/
│ │ ├── build.gradle
│ │ └── src/
│ │ ├── androidTest/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── playbacktests/
│ │ │ └── gts/
│ │ │ ├── CommonEncryptionDrmTest.java
│ │ │ ├── DashDownloadTest.java
│ │ │ ├── DashStreamingTest.java
│ │ │ ├── DashTestData.java
│ │ │ ├── DashTestRunner.java
│ │ │ ├── DashWidevineOfflineTest.java
│ │ │ └── EnumerateDecodersTest.java
│ │ └── main/
│ │ └── AndroidManifest.xml
│ ├── publish.gradle
│ ├── settings.gradle
│ ├── testutils/
│ │ ├── build.gradle
│ │ └── src/
│ │ ├── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── testutil/
│ │ │ │ ├── Action.java
│ │ │ │ ├── ActionSchedule.java
│ │ │ │ ├── AutoAdvancingFakeClock.java
│ │ │ │ ├── DebugRenderersFactory.java
│ │ │ │ ├── DecoderCountersUtil.java
│ │ │ │ ├── DummyMainThread.java
│ │ │ │ ├── Dumper.java
│ │ │ │ ├── ExoHostedTest.java
│ │ │ │ ├── ExoPlayerTestRunner.java
│ │ │ │ ├── ExtractorAsserts.java
│ │ │ │ ├── FakeAdaptiveDataSet.java
│ │ │ │ ├── FakeAdaptiveMediaPeriod.java
│ │ │ │ ├── FakeAdaptiveMediaSource.java
│ │ │ │ ├── FakeChunkSource.java
│ │ │ │ ├── FakeClock.java
│ │ │ │ ├── FakeDataSet.java
│ │ │ │ ├── FakeDataSource.java
│ │ │ │ ├── FakeExtractorInput.java
│ │ │ │ ├── FakeExtractorOutput.java
│ │ │ │ ├── FakeMediaPeriod.java
│ │ │ │ ├── FakeMediaSource.java
│ │ │ │ ├── FakeRenderer.java
│ │ │ │ ├── FakeSampleStream.java
│ │ │ │ ├── FakeTimeline.java
│ │ │ │ ├── FakeTrackOutput.java
│ │ │ │ ├── HostActivity.java
│ │ │ │ ├── LogcatMetricsLogger.java
│ │ │ │ ├── MetricsLogger.java
│ │ │ │ └── TestUtil.java
│ │ │ └── res/
│ │ │ └── layout/
│ │ │ └── exo_testutils_host_activity.xml
│ │ └── test/
│ │ ├── AndroidManifest.xml
│ │ └── java/
│ │ └── com/
│ │ └── google/
│ │ └── android/
│ │ └── exoplayer2/
│ │ └── testutil/
│ │ ├── FakeAdaptiveDataSetTest.java
│ │ ├── FakeClockTest.java
│ │ ├── FakeDataSetTest.java
│ │ └── FakeDataSourceTest.java
│ └── testutils_robolectric/
│ ├── build.gradle
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ └── java/
│ └── com/
│ └── google/
│ └── android/
│ └── exoplayer2/
│ └── testutil/
│ ├── CacheAsserts.java
│ ├── DefaultRenderersFactoryAsserts.java
│ ├── FakeMediaChunk.java
│ ├── FakeMediaChunkIterator.java
│ ├── FakeMediaClockRenderer.java
│ ├── FakeShuffleOrder.java
│ ├── FakeTrackSelection.java
│ ├── FakeTrackSelector.java
│ ├── MediaPeriodAsserts.java
│ ├── MediaSourceTestRunner.java
│ ├── OggTestData.java
│ ├── RobolectricUtil.java
│ ├── StubExoPlayer.java
│ ├── TestDownloadManagerListener.java
│ └── TimelineAsserts.java
├── fastlane/
│ └── metadata/
│ └── android/
│ └── en-US/
│ ├── full_description.txt
│ └── short_description.txt
├── filepicker-lib/
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── arte/
│ │ └── programar/
│ │ └── materialfile/
│ │ ├── MaterialFilePicker.java
│ │ ├── filter/
│ │ │ ├── CompositeFilter.java
│ │ │ ├── FileFilter.java
│ │ │ ├── HiddenFilter.java
│ │ │ └── PatternFilter.java
│ │ ├── ui/
│ │ │ ├── DirectoryAdapter.java
│ │ │ ├── DirectoryFragment.java
│ │ │ ├── FilePickerActivity.java
│ │ │ ├── OnItemClickListener.java
│ │ │ └── ThrottleClickListener.java
│ │ ├── utils/
│ │ │ ├── FileComparator.java
│ │ │ ├── FileTypeUtils.java
│ │ │ └── FileUtils.java
│ │ └── widget/
│ │ └── EmptyRecyclerView.java
│ └── res/
│ ├── drawable/
│ │ ├── bg_clickable.xml
│ │ ├── ic_app_apk.xml
│ │ ├── ic_app_certificate.xml
│ │ ├── ic_app_compress.xml
│ │ ├── ic_app_database.xml
│ │ ├── ic_app_directory.xml
│ │ ├── ic_app_document.xml
│ │ ├── ic_app_drawing.xml
│ │ ├── ic_app_file.xml
│ │ ├── ic_app_image.xml
│ │ ├── ic_app_json.xml
│ │ ├── ic_app_music.xml
│ │ ├── ic_app_pdf.xml
│ │ ├── ic_app_presentation.xml
│ │ ├── ic_app_spreadsheet.xml
│ │ ├── ic_app_video.xml
│ │ └── ic_close.xml
│ ├── drawable-night/
│ │ └── ic_close.xml
│ ├── drawable-v21/
│ │ └── bg_clickable.xml
│ ├── layout/
│ │ ├── activity_file_picker.xml
│ │ ├── fragment_directory.xml
│ │ └── item_file.xml
│ ├── values/
│ │ ├── attr.xml
│ │ ├── colors.xml
│ │ ├── dimen.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ ├── values-cs/
│ │ └── strings.xml
│ ├── values-de/
│ │ └── strings.xml
│ ├── values-es/
│ │ └── strings.xml
│ ├── values-night/
│ │ ├── colors.xml
│ │ └── styles.xml
│ ├── values-night-v21/
│ │ └── styles.xml
│ ├── values-night-v23/
│ │ └── styles.xml
│ ├── values-night-v27/
│ │ └── styles.xml
│ ├── values-night-v29/
│ │ └── styles.xml
│ ├── values-ru/
│ │ └── strings.xml
│ ├── values-sk/
│ │ └── strings.xml
│ ├── values-v19/
│ │ └── styles.xml
│ ├── values-v21/
│ │ └── styles.xml
│ ├── values-v23/
│ │ └── styles.xml
│ ├── values-v27/
│ │ └── styles.xml
│ ├── values-v29/
│ │ └── styles.xml
│ └── values-zh/
│ └── strings.xml
├── fragment-1.1.0/
│ ├── .gitignore
│ ├── LICENSE
│ ├── build.gradle
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ └── java/
│ └── androidx/
│ └── fragment/
│ └── app/
│ ├── BackStackRecord.java
│ ├── BackStackState.java
│ ├── DialogFragment.java
│ ├── Fragment.java
│ ├── FragmentActivity.java
│ ├── FragmentContainer.java
│ ├── FragmentController.java
│ ├── FragmentFactory.java
│ ├── FragmentHostCallback.java
│ ├── FragmentManager.java
│ ├── FragmentManagerImpl.java
│ ├── FragmentManagerNonConfig.java
│ ├── FragmentManagerState.java
│ ├── FragmentManagerViewModel.java
│ ├── FragmentPagerAdapter.java
│ ├── FragmentState.java
│ ├── FragmentStatePagerAdapter.java
│ ├── FragmentTabHost.java
│ ├── FragmentTransaction.java
│ ├── FragmentTransition.java
│ ├── FragmentTransitionCompat21.java
│ ├── FragmentTransitionImpl.java
│ ├── FragmentViewLifecycleOwner.java
│ ├── ListFragment.java
│ └── SuperNotCalledException.java
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── leanback-1.0.0/
│ ├── .gitignore
│ ├── LICENSE
│ ├── build.gradle
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── androidx/
│ │ └── leanback/
│ │ ├── animation/
│ │ │ ├── LogAccelerateInterpolator.java
│ │ │ └── LogDecelerateInterpolator.java
│ │ ├── app/
│ │ │ ├── BackgroundFragment.java
│ │ │ ├── BackgroundManager.java
│ │ │ ├── BaseFragment.java
│ │ │ ├── BaseRowFragment.java
│ │ │ ├── BaseRowSupportFragment.java
│ │ │ ├── BaseSupportFragment.java
│ │ │ ├── BrandedFragment.java
│ │ │ ├── BrandedSupportFragment.java
│ │ │ ├── BrowseFragment.java
│ │ │ ├── BrowseSupportFragment.java
│ │ │ ├── DetailsBackgroundVideoHelper.java
│ │ │ ├── DetailsFragment.java
│ │ │ ├── DetailsFragmentBackgroundController.java
│ │ │ ├── DetailsSupportFragment.java
│ │ │ ├── DetailsSupportFragmentBackgroundController.java
│ │ │ ├── ErrorFragment.java
│ │ │ ├── ErrorSupportFragment.java
│ │ │ ├── FragmentUtil.java
│ │ │ ├── GuidedStepFragment.java
│ │ │ ├── GuidedStepRootLayout.java
│ │ │ ├── GuidedStepSupportFragment.java
│ │ │ ├── HeadersFragment.java
│ │ │ ├── HeadersSupportFragment.java
│ │ │ ├── ListRowDataAdapter.java
│ │ │ ├── OnboardingFragment.java
│ │ │ ├── OnboardingSupportFragment.java
│ │ │ ├── PermissionHelper.java
│ │ │ ├── PlaybackFragment.java
│ │ │ ├── PlaybackFragmentGlueHost.java
│ │ │ ├── PlaybackSupportFragment.java
│ │ │ ├── PlaybackSupportFragmentGlueHost.java
│ │ │ ├── ProgressBarManager.java
│ │ │ ├── RowsFragment.java
│ │ │ ├── RowsSupportFragment.java
│ │ │ ├── SearchFragment.java
│ │ │ ├── SearchSupportFragment.java
│ │ │ ├── VerticalGridFragment.java
│ │ │ ├── VerticalGridSupportFragment.java
│ │ │ ├── VideoFragment.java
│ │ │ ├── VideoFragmentGlueHost.java
│ │ │ ├── VideoSupportFragment.java
│ │ │ ├── VideoSupportFragmentGlueHost.java
│ │ │ └── package-info.java
│ │ ├── database/
│ │ │ └── CursorMapper.java
│ │ ├── graphics/
│ │ │ ├── BoundsRule.java
│ │ │ ├── ColorFilterCache.java
│ │ │ ├── ColorFilterDimmer.java
│ │ │ ├── ColorOverlayDimmer.java
│ │ │ ├── CompositeDrawable.java
│ │ │ └── FitWidthBitmapDrawable.java
│ │ ├── media/
│ │ │ ├── MediaControllerAdapter.java
│ │ │ ├── MediaControllerGlue.java
│ │ │ ├── MediaPlayerAdapter.java
│ │ │ ├── MediaPlayerGlue.java
│ │ │ ├── PlaybackBannerControlGlue.java
│ │ │ ├── PlaybackBaseControlGlue.java
│ │ │ ├── PlaybackControlGlue.java
│ │ │ ├── PlaybackGlue.java
│ │ │ ├── PlaybackGlueHost.java
│ │ │ ├── PlaybackTransportControlGlue.java
│ │ │ ├── PlayerAdapter.java
│ │ │ └── SurfaceHolderGlueHost.java
│ │ ├── package-info.java
│ │ ├── system/
│ │ │ └── Settings.java
│ │ ├── transition/
│ │ │ ├── CustomChangeBounds.java
│ │ │ ├── FadeAndShortSlide.java
│ │ │ ├── LeanbackTransitionHelper.java
│ │ │ ├── ParallaxTransition.java
│ │ │ ├── Scale.java
│ │ │ ├── SlideKitkat.java
│ │ │ ├── SlideNoPropagation.java
│ │ │ ├── TransitionEpicenterCallback.java
│ │ │ ├── TransitionHelper.java
│ │ │ ├── TransitionListener.java
│ │ │ └── TranslationAnimationCreator.java
│ │ ├── util/
│ │ │ ├── MathUtil.java
│ │ │ └── StateMachine.java
│ │ └── widget/
│ │ ├── AbstractDetailsDescriptionPresenter.java
│ │ ├── AbstractMediaItemPresenter.java
│ │ ├── AbstractMediaListHeaderPresenter.java
│ │ ├── Action.java
│ │ ├── ActionPresenterSelector.java
│ │ ├── ArrayObjectAdapter.java
│ │ ├── BackgroundHelper.java
│ │ ├── BaseCardView.java
│ │ ├── BaseGridView.java
│ │ ├── BaseOnItemViewClickedListener.java
│ │ ├── BaseOnItemViewSelectedListener.java
│ │ ├── BrowseFrameLayout.java
│ │ ├── BrowseRowsFrameLayout.java
│ │ ├── CheckableImageView.java
│ │ ├── ClassPresenterSelector.java
│ │ ├── ControlBar.java
│ │ ├── ControlBarPresenter.java
│ │ ├── ControlButtonPresenterSelector.java
│ │ ├── CursorObjectAdapter.java
│ │ ├── DetailsOverviewLogoPresenter.java
│ │ ├── DetailsOverviewRow.java
│ │ ├── DetailsOverviewRowPresenter.java
│ │ ├── DetailsOverviewSharedElementHelper.java
│ │ ├── DetailsParallax.java
│ │ ├── DetailsParallaxDrawable.java
│ │ ├── DiffCallback.java
│ │ ├── DividerPresenter.java
│ │ ├── DividerRow.java
│ │ ├── FacetProvider.java
│ │ ├── FacetProviderAdapter.java
│ │ ├── FocusHighlight.java
│ │ ├── FocusHighlightHandler.java
│ │ ├── FocusHighlightHelper.java
│ │ ├── ForegroundHelper.java
│ │ ├── FragmentAnimationProvider.java
│ │ ├── FullWidthDetailsOverviewRowPresenter.java
│ │ ├── FullWidthDetailsOverviewSharedElementHelper.java
│ │ ├── Grid.java
│ │ ├── GridLayoutManager.java
│ │ ├── GuidanceStylingRelativeLayout.java
│ │ ├── GuidanceStylist.java
│ │ ├── GuidedAction.java
│ │ ├── GuidedActionAdapter.java
│ │ ├── GuidedActionAdapterGroup.java
│ │ ├── GuidedActionAutofillSupport.java
│ │ ├── GuidedActionDiffCallback.java
│ │ ├── GuidedActionEditText.java
│ │ ├── GuidedActionItemContainer.java
│ │ ├── GuidedActionsRelativeLayout.java
│ │ ├── GuidedActionsStylist.java
│ │ ├── GuidedDatePickerAction.java
│ │ ├── HeaderItem.java
│ │ ├── HorizontalGridView.java
│ │ ├── HorizontalHoverCardSwitcher.java
│ │ ├── ImageCardView.java
│ │ ├── ImeKeyMonitor.java
│ │ ├── InvisibleRowPresenter.java
│ │ ├── ItemAlignment.java
│ │ ├── ItemAlignmentFacet.java
│ │ ├── ItemAlignmentFacetHelper.java
│ │ ├── ItemBridgeAdapter.java
│ │ ├── ItemBridgeAdapterShadowOverlayWrapper.java
│ │ ├── ListRow.java
│ │ ├── ListRowHoverCardView.java
│ │ ├── ListRowPresenter.java
│ │ ├── ListRowView.java
│ │ ├── MediaItemActionPresenter.java
│ │ ├── MediaNowPlayingView.java
│ │ ├── MediaRowFocusView.java
│ │ ├── MultiActionsProvider.java
│ │ ├── NonOverlappingFrameLayout.java
│ │ ├── NonOverlappingLinearLayout.java
│ │ ├── NonOverlappingLinearLayoutWithForeground.java
│ │ ├── NonOverlappingRelativeLayout.java
│ │ ├── NonOverlappingView.java
│ │ ├── ObjectAdapter.java
│ │ ├── OnActionClickedListener.java
│ │ ├── OnChildLaidOutListener.java
│ │ ├── OnChildSelectedListener.java
│ │ ├── OnChildViewHolderSelectedListener.java
│ │ ├── OnItemViewClickedListener.java
│ │ ├── OnItemViewSelectedListener.java
│ │ ├── PageRow.java
│ │ ├── PagingIndicator.java
│ │ ├── Parallax.java
│ │ ├── ParallaxEffect.java
│ │ ├── ParallaxTarget.java
│ │ ├── PersistentFocusWrapper.java
│ │ ├── PlaybackControlsPresenter.java
│ │ ├── PlaybackControlsRow.java
│ │ ├── PlaybackControlsRowPresenter.java
│ │ ├── PlaybackControlsRowView.java
│ │ ├── PlaybackRowPresenter.java
│ │ ├── PlaybackSeekDataProvider.java
│ │ ├── PlaybackSeekUi.java
│ │ ├── PlaybackTransportRowPresenter.java
│ │ ├── PlaybackTransportRowView.java
│ │ ├── Presenter.java
│ │ ├── PresenterSelector.java
│ │ ├── PresenterSwitcher.java
│ │ ├── RecyclerViewParallax.java
│ │ ├── ResizingTextView.java
│ │ ├── RoundedRectHelper.java
│ │ ├── RoundedRectHelperApi21.java
│ │ ├── Row.java
│ │ ├── RowContainerView.java
│ │ ├── RowHeaderPresenter.java
│ │ ├── RowHeaderView.java
│ │ ├── RowPresenter.java
│ │ ├── ScaleFrameLayout.java
│ │ ├── SearchBar.java
│ │ ├── SearchEditText.java
│ │ ├── SearchOrbView.java
│ │ ├── SectionRow.java
│ │ ├── SeekBar.java
│ │ ├── ShadowHelper.java
│ │ ├── ShadowHelperApi21.java
│ │ ├── ShadowOverlayContainer.java
│ │ ├── ShadowOverlayHelper.java
│ │ ├── SinglePresenterSelector.java
│ │ ├── SingleRow.java
│ │ ├── SparseArrayObjectAdapter.java
│ │ ├── SpeechOrbView.java
│ │ ├── SpeechRecognitionCallback.java
│ │ ├── StaggeredGrid.java
│ │ ├── StaggeredGridDefault.java
│ │ ├── StaticShadowHelper.java
│ │ ├── StreamingTextView.java
│ │ ├── ThumbsBar.java
│ │ ├── TitleHelper.java
│ │ ├── TitleView.java
│ │ ├── TitleViewAdapter.java
│ │ ├── Util.java
│ │ ├── VerticalGridPresenter.java
│ │ ├── VerticalGridView.java
│ │ ├── VideoSurfaceView.java
│ │ ├── ViewHolderTask.java
│ │ ├── ViewsStateBundle.java
│ │ ├── Visibility.java
│ │ ├── WindowAlignment.java
│ │ ├── package-info.java
│ │ └── picker/
│ │ ├── DatePicker.java
│ │ ├── Picker.java
│ │ ├── PickerColumn.java
│ │ ├── PickerUtility.java
│ │ └── TimePicker.java
│ └── res/
│ ├── anim/
│ │ ├── lb_decelerator_2.xml
│ │ └── lb_decelerator_4.xml
│ ├── animator/
│ │ ├── lb_guidedactions_item_pressed.xml
│ │ ├── lb_guidedactions_item_unpressed.xml
│ │ ├── lb_guidedstep_slide_down.xml
│ │ ├── lb_guidedstep_slide_up.xml
│ │ ├── lb_onboarding_description_enter.xml
│ │ ├── lb_onboarding_logo_enter.xml
│ │ ├── lb_onboarding_logo_exit.xml
│ │ ├── lb_onboarding_page_indicator_enter.xml
│ │ ├── lb_onboarding_page_indicator_fade_in.xml
│ │ ├── lb_onboarding_page_indicator_fade_out.xml
│ │ ├── lb_onboarding_start_button_fade_in.xml
│ │ ├── lb_onboarding_start_button_fade_out.xml
│ │ ├── lb_onboarding_title_enter.xml
│ │ ├── lb_playback_bg_fade_in.xml
│ │ ├── lb_playback_bg_fade_out.xml
│ │ ├── lb_playback_controls_fade_in.xml
│ │ ├── lb_playback_controls_fade_out.xml
│ │ ├── lb_playback_description_fade_in.xml
│ │ ├── lb_playback_description_fade_out.xml
│ │ ├── lb_playback_rows_fade_in.xml
│ │ └── lb_playback_rows_fade_out.xml
│ ├── animator-v21/
│ │ ├── lb_onboarding_description_enter.xml
│ │ ├── lb_onboarding_logo_enter.xml
│ │ ├── lb_onboarding_logo_exit.xml
│ │ ├── lb_onboarding_page_indicator_enter.xml
│ │ ├── lb_onboarding_title_enter.xml
│ │ ├── lb_playback_bg_fade_in.xml
│ │ ├── lb_playback_bg_fade_out.xml
│ │ └── lb_playback_description_fade_out.xml
│ ├── drawable/
│ │ ├── lb_background.xml
│ │ ├── lb_card_foreground.xml
│ │ ├── lb_control_button_primary.xml
│ │ ├── lb_control_button_secondary.xml
│ │ ├── lb_headers_right_fading.xml
│ │ ├── lb_onboarding_start_button_background.xml
│ │ ├── lb_playback_now_playing_bar.xml
│ │ ├── lb_playback_progress_bar.xml
│ │ ├── lb_search_orb.xml
│ │ └── lb_speech_orb.xml
│ ├── drawable-v21/
│ │ ├── lb_action_bg.xml
│ │ ├── lb_card_foreground.xml
│ │ ├── lb_control_button_primary.xml
│ │ ├── lb_control_button_secondary.xml
│ │ └── lb_selectable_item_rounded_rect.xml
│ ├── layout/
│ │ ├── lb_action_1_line.xml
│ │ ├── lb_action_2_lines.xml
│ │ ├── lb_background_window.xml
│ │ ├── lb_browse_fragment.xml
│ │ ├── lb_browse_title.xml
│ │ ├── lb_control_bar.xml
│ │ ├── lb_control_button_primary.xml
│ │ ├── lb_control_button_secondary.xml
│ │ ├── lb_details_description.xml
│ │ ├── lb_details_fragment.xml
│ │ ├── lb_details_overview.xml
│ │ ├── lb_divider.xml
│ │ ├── lb_error_fragment.xml
│ │ ├── lb_fullwidth_details_overview.xml
│ │ ├── lb_fullwidth_details_overview_logo.xml
│ │ ├── lb_guidance.xml
│ │ ├── lb_guidedactions.xml
│ │ ├── lb_guidedactions_datepicker_item.xml
│ │ ├── lb_guidedactions_item.xml
│ │ ├── lb_guidedbuttonactions.xml
│ │ ├── lb_guidedstep_background.xml
│ │ ├── lb_guidedstep_fragment.xml
│ │ ├── lb_header.xml
│ │ ├── lb_headers_fragment.xml
│ │ ├── lb_image_card_view.xml
│ │ ├── lb_image_card_view_themed_badge_left.xml
│ │ ├── lb_image_card_view_themed_badge_right.xml
│ │ ├── lb_image_card_view_themed_content.xml
│ │ ├── lb_image_card_view_themed_title.xml
│ │ ├── lb_list_row.xml
│ │ ├── lb_list_row_hovercard.xml
│ │ ├── lb_media_item_number_view_flipper.xml
│ │ ├── lb_media_list_header.xml
│ │ ├── lb_onboarding_fragment.xml
│ │ ├── lb_picker.xml
│ │ ├── lb_picker_column.xml
│ │ ├── lb_picker_item.xml
│ │ ├── lb_picker_separator.xml
│ │ ├── lb_playback_controls.xml
│ │ ├── lb_playback_controls_row.xml
│ │ ├── lb_playback_fragment.xml
│ │ ├── lb_playback_now_playing_bars.xml
│ │ ├── lb_playback_transport_controls.xml
│ │ ├── lb_playback_transport_controls_row.xml
│ │ ├── lb_row_container.xml
│ │ ├── lb_row_header.xml
│ │ ├── lb_row_media_item.xml
│ │ ├── lb_row_media_item_action.xml
│ │ ├── lb_rows_fragment.xml
│ │ ├── lb_search_bar.xml
│ │ ├── lb_search_fragment.xml
│ │ ├── lb_search_orb.xml
│ │ ├── lb_section_header.xml
│ │ ├── lb_shadow.xml
│ │ ├── lb_speech_orb.xml
│ │ ├── lb_title_view.xml
│ │ ├── lb_vertical_grid.xml
│ │ ├── lb_vertical_grid_fragment.xml
│ │ ├── lb_video_surface.xml
│ │ └── video_surface_fragment.xml
│ ├── raw/
│ │ ├── lb_voice_failure.ogg
│ │ ├── lb_voice_no_input.ogg
│ │ ├── lb_voice_open.ogg
│ │ └── lb_voice_success.ogg
│ ├── transition-v19/
│ │ ├── lb_browse_headers_in.xml
│ │ └── lb_browse_headers_out.xml
│ ├── transition-v21/
│ │ ├── lb_browse_enter_transition.xml
│ │ ├── lb_browse_entrance_transition.xml
│ │ ├── lb_browse_headers_in.xml
│ │ ├── lb_browse_headers_out.xml
│ │ ├── lb_browse_return_transition.xml
│ │ ├── lb_details_enter_transition.xml
│ │ ├── lb_details_return_transition.xml
│ │ ├── lb_enter_transition.xml
│ │ ├── lb_guidedstep_activity_enter.xml
│ │ ├── lb_guidedstep_activity_enter_bottom.xml
│ │ ├── lb_return_transition.xml
│ │ ├── lb_shared_element_enter_transition.xml
│ │ ├── lb_shared_element_return_transition.xml
│ │ ├── lb_title_in.xml
│ │ ├── lb_title_out.xml
│ │ ├── lb_vertical_grid_enter_transition.xml
│ │ ├── lb_vertical_grid_entrance_transition.xml
│ │ └── lb_vertical_grid_return_transition.xml
│ ├── values/
│ │ └── values.xml
│ ├── values-af/
│ │ └── values-af.xml
│ ├── values-am/
│ │ └── values-am.xml
│ ├── values-ar/
│ │ └── values-ar.xml
│ ├── values-as/
│ │ └── values-as.xml
│ ├── values-az/
│ │ └── values-az.xml
│ ├── values-b+sr+Latn/
│ │ └── values-b+sr+Latn.xml
│ ├── values-be/
│ │ └── values-be.xml
│ ├── values-bg/
│ │ └── values-bg.xml
│ ├── values-bn/
│ │ └── values-bn.xml
│ ├── values-bs/
│ │ └── values-bs.xml
│ ├── values-ca/
│ │ └── values-ca.xml
│ ├── values-cs/
│ │ └── values-cs.xml
│ ├── values-da/
│ │ └── values-da.xml
│ ├── values-de/
│ │ └── values-de.xml
│ ├── values-el/
│ │ └── values-el.xml
│ ├── values-en-rAU/
│ │ └── values-en-rAU.xml
│ ├── values-en-rCA/
│ │ └── values-en-rCA.xml
│ ├── values-en-rGB/
│ │ └── values-en-rGB.xml
│ ├── values-en-rIN/
│ │ └── values-en-rIN.xml
│ ├── values-en-rXC/
│ │ └── values-en-rXC.xml
│ ├── values-es/
│ │ └── values-es.xml
│ ├── values-es-rUS/
│ │ └── values-es-rUS.xml
│ ├── values-et/
│ │ └── values-et.xml
│ ├── values-eu/
│ │ └── values-eu.xml
│ ├── values-fa/
│ │ └── values-fa.xml
│ ├── values-fi/
│ │ └── values-fi.xml
│ ├── values-fr/
│ │ └── values-fr.xml
│ ├── values-fr-rCA/
│ │ └── values-fr-rCA.xml
│ ├── values-gl/
│ │ └── values-gl.xml
│ ├── values-gu/
│ │ └── values-gu.xml
│ ├── values-hi/
│ │ └── values-hi.xml
│ ├── values-hr/
│ │ └── values-hr.xml
│ ├── values-hu/
│ │ └── values-hu.xml
│ ├── values-hy/
│ │ └── values-hy.xml
│ ├── values-in/
│ │ └── values-in.xml
│ ├── values-is/
│ │ └── values-is.xml
│ ├── values-it/
│ │ └── values-it.xml
│ ├── values-iw/
│ │ └── values-iw.xml
│ ├── values-ja/
│ │ └── values-ja.xml
│ ├── values-ka/
│ │ └── values-ka.xml
│ ├── values-kk/
│ │ └── values-kk.xml
│ ├── values-km/
│ │ └── values-km.xml
│ ├── values-kn/
│ │ └── values-kn.xml
│ ├── values-ko/
│ │ └── values-ko.xml
│ ├── values-ky/
│ │ └── values-ky.xml
│ ├── values-ldrtl-v17/
│ │ └── values-ldrtl-v17.xml
│ ├── values-lo/
│ │ └── values-lo.xml
│ ├── values-lt/
│ │ └── values-lt.xml
│ ├── values-lv/
│ │ └── values-lv.xml
│ ├── values-mk/
│ │ └── values-mk.xml
│ ├── values-ml/
│ │ └── values-ml.xml
│ ├── values-mn/
│ │ └── values-mn.xml
│ ├── values-mr/
│ │ └── values-mr.xml
│ ├── values-ms/
│ │ └── values-ms.xml
│ ├── values-my/
│ │ └── values-my.xml
│ ├── values-nb/
│ │ └── values-nb.xml
│ ├── values-ne/
│ │ └── values-ne.xml
│ ├── values-nl/
│ │ └── values-nl.xml
│ ├── values-or/
│ │ └── values-or.xml
│ ├── values-pa/
│ │ └── values-pa.xml
│ ├── values-pl/
│ │ └── values-pl.xml
│ ├── values-pt/
│ │ └── values-pt.xml
│ ├── values-pt-rBR/
│ │ └── values-pt-rBR.xml
│ ├── values-pt-rPT/
│ │ └── values-pt-rPT.xml
│ ├── values-ro/
│ │ └── values-ro.xml
│ ├── values-ru/
│ │ └── values-ru.xml
│ ├── values-si/
│ │ └── values-si.xml
│ ├── values-sk/
│ │ └── values-sk.xml
│ ├── values-sl/
│ │ └── values-sl.xml
│ ├── values-sq/
│ │ └── values-sq.xml
│ ├── values-sr/
│ │ └── values-sr.xml
│ ├── values-sv/
│ │ └── values-sv.xml
│ ├── values-sw/
│ │ └── values-sw.xml
│ ├── values-ta/
│ │ └── values-ta.xml
│ ├── values-te/
│ │ └── values-te.xml
│ ├── values-th/
│ │ └── values-th.xml
│ ├── values-tl/
│ │ └── values-tl.xml
│ ├── values-tr/
│ │ └── values-tr.xml
│ ├── values-uk/
│ │ └── values-uk.xml
│ ├── values-ur/
│ │ └── values-ur.xml
│ ├── values-uz/
│ │ └── values-uz.xml
│ ├── values-v18/
│ │ └── values-v18.xml
│ ├── values-v19/
│ │ └── values-v19.xml
│ ├── values-v21/
│ │ └── values-v21.xml
│ ├── values-v22/
│ │ └── values-v22.xml
│ ├── values-vi/
│ │ └── values-vi.xml
│ ├── values-zh-rCN/
│ │ └── values-zh-rCN.xml
│ ├── values-zh-rHK/
│ │ └── values-zh-rHK.xml
│ ├── values-zh-rTW/
│ │ └── values-zh-rTW.xml
│ └── values-zu/
│ └── values-zu.xml
├── leanbackassistant/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── liskovsoft/
│ │ │ └── leanbackassistant/
│ │ │ ├── channels/
│ │ │ │ ├── ChannelsProvider.java
│ │ │ │ ├── UpdateChannelsJobService.java
│ │ │ │ ├── UpdateChannelsReceiver.java
│ │ │ │ ├── UpdateChannelsTask.java
│ │ │ │ └── UpdateChannelsWorker.java
│ │ │ ├── media/
│ │ │ │ ├── Clip.java
│ │ │ │ ├── ClipService.java
│ │ │ │ ├── ClipServiceCached.java
│ │ │ │ ├── Playlist.java
│ │ │ │ └── scheduler/
│ │ │ │ └── ClipData.java
│ │ │ ├── recommendations/
│ │ │ │ ├── RecommendationBuilder.java
│ │ │ │ └── RecommendationsProvider.java
│ │ │ ├── search/
│ │ │ │ ├── MockDatabase.java
│ │ │ │ ├── SearchableActivity.java
│ │ │ │ └── VideoContentProvider.java
│ │ │ └── utils/
│ │ │ └── AppUtil.java
│ │ └── res/
│ │ ├── values/
│ │ │ ├── colors.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ ├── values-es/
│ │ │ └── strings.xml
│ │ ├── values-ru/
│ │ │ └── strings.xml
│ │ ├── values-tr/
│ │ │ └── strings.xml
│ │ ├── values-uk/
│ │ │ └── strings.xml
│ │ └── xml/
│ │ └── searchable.xml
│ ├── stbeta/
│ │ ├── AndroidManifest.xml
│ │ └── res/
│ │ ├── values/
│ │ │ └── strings.xml
│ │ └── xml/
│ │ └── searchable.xml
│ ├── stfdroid/
│ │ ├── AndroidManifest.xml
│ │ └── res/
│ │ ├── values/
│ │ │ └── strings.xml
│ │ └── xml/
│ │ └── searchable.xml
│ └── ststable/
│ ├── AndroidManifest.xml
│ └── res/
│ ├── values/
│ │ └── strings.xml
│ └── xml/
│ └── searchable.xml
├── settings.gradle
├── slidableactivity/
│ ├── .gitignore
│ ├── LICENSE.md
│ ├── README.md
│ ├── build.gradle
│ ├── gradle.properties
│ └── src/
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── r0adkll/
│ │ │ └── slidr/
│ │ │ ├── ColorPanelSlideListener.java
│ │ │ ├── ConfigPanelSlideListener.java
│ │ │ ├── FragmentPanelSlideListener.java
│ │ │ ├── Slidr.java
│ │ │ ├── model/
│ │ │ │ ├── SlidrConfig.java
│ │ │ │ ├── SlidrInterface.java
│ │ │ │ ├── SlidrListener.java
│ │ │ │ ├── SlidrListenerAdapter.java
│ │ │ │ └── SlidrPosition.java
│ │ │ ├── util/
│ │ │ │ └── ViewDragHelper.java
│ │ │ └── widget/
│ │ │ ├── ScrimRenderer.java
│ │ │ └── SliderPanel.java
│ │ └── res/
│ │ └── values/
│ │ └── ids.xml
│ └── test/
│ └── java/
│ └── com/
│ └── r0adkll/
│ └── slidr/
│ └── widget/
│ ├── ScrimRendererTest.java
│ └── SliderPanelTest.java
└── smarttubetv/
├── build.gradle
├── google-services.json
├── multidex-keep.pro
├── proguard-rules.pro
└── src/
├── main/
│ ├── AndroidManifest.xml
│ ├── assets/
│ │ └── common.properties
│ ├── java/
│ │ └── com/
│ │ └── liskovsoft/
│ │ └── smartyoutubetv2/
│ │ └── tv/
│ │ ├── adapter/
│ │ │ ├── DeferredVideoGroupObjectAdapter.java
│ │ │ ├── HeaderVideoGroupObjectAdapter.java
│ │ │ ├── VideoGroupObjectAdapter.java
│ │ │ └── vineyard/
│ │ │ ├── PaginationAdapter.java
│ │ │ └── TagAdapter.java
│ │ ├── launchers/
│ │ │ ├── ChannelsLauncherActivity.java
│ │ │ ├── GamesLauncherActivity.java
│ │ │ ├── HistoryLauncherActivity.java
│ │ │ ├── HomeLauncherActivity.java
│ │ │ ├── MusicLauncherActivity.java
│ │ │ ├── NewsLauncherActivity.java
│ │ │ ├── PlaylistsLauncherActivity.java
│ │ │ ├── SearchLauncherActivity.java
│ │ │ └── SubscriptionsLauncherActivity.java
│ │ ├── presenter/
│ │ │ ├── ChannelCardPresenter.java
│ │ │ ├── ChannelHeaderPresenter.java
│ │ │ ├── CustomListRowPresenter.java
│ │ │ ├── CustomVerticalGridPresenter.java
│ │ │ ├── DetailsDescriptionPresenter.java
│ │ │ ├── GridItemPresenter.java
│ │ │ ├── IconHeaderItemPresenter.java
│ │ │ ├── SearchFieldPresenter.java
│ │ │ ├── SettingsCardPresenter.java
│ │ │ ├── ShortsCardPresenter.java
│ │ │ ├── TinyCardPresenter.java
│ │ │ ├── VideoCardPresenter.java
│ │ │ ├── base/
│ │ │ │ ├── LongClickPresenter.java
│ │ │ │ └── OnItemLongPressedListener.java
│ │ │ └── vineyard/
│ │ │ ├── IconItemPresenter.java
│ │ │ ├── LoadingPresenter.java
│ │ │ └── TagPresenter.java
│ │ ├── ui/
│ │ │ ├── adddevice/
│ │ │ │ ├── AddDeviceActivity.java
│ │ │ │ └── AddDeviceFragment.java
│ │ │ ├── browse/
│ │ │ │ ├── BrowseActivity.java
│ │ │ │ ├── BrowseFragment.java
│ │ │ │ ├── BrowseSectionFragmentFactory.java
│ │ │ │ ├── CategoryFragmentFactory.java.old
│ │ │ │ ├── SectionHeaderItem.java
│ │ │ │ ├── dialog/
│ │ │ │ │ └── ErrorDialogFragment.java
│ │ │ │ ├── interfaces/
│ │ │ │ │ ├── Section.java
│ │ │ │ │ ├── SettingsSection.java
│ │ │ │ │ └── VideoSection.java
│ │ │ │ ├── settings/
│ │ │ │ │ └── SettingsGridFragment.java
│ │ │ │ └── video/
│ │ │ │ ├── GridFragmentHelper.java
│ │ │ │ ├── MultiVideoGridFragment.java
│ │ │ │ ├── MultipleRowsFragment.java
│ │ │ │ ├── ShortsGridFragment.java
│ │ │ │ ├── VideoGridFragment.java
│ │ │ │ └── VideoRowsFragment.java
│ │ │ ├── channel/
│ │ │ │ ├── ChannelActivity.java
│ │ │ │ └── ChannelFragment.java
│ │ │ ├── channeluploads/
│ │ │ │ ├── ChannelUploadsActivity.java
│ │ │ │ └── ChannelUploadsFragment.java
│ │ │ ├── common/
│ │ │ │ ├── DisplayUtils.java
│ │ │ │ ├── LeanbackActivity.java
│ │ │ │ ├── UriBackgroundManager.java
│ │ │ │ └── keyhandler/
│ │ │ │ ├── DoubleBackManager.java
│ │ │ │ ├── DoubleBackManager2.java
│ │ │ │ └── LongClickManager.java
│ │ │ ├── dialogs/
│ │ │ │ ├── AppDialogActivity.java
│ │ │ │ ├── AppDialogFragment.java
│ │ │ │ ├── AppPreferenceManager.java
│ │ │ │ └── other/
│ │ │ │ ├── ChatPreference.java
│ │ │ │ ├── ChatPreferenceDialogFragment.java
│ │ │ │ ├── CommentsPreference.java
│ │ │ │ ├── CommentsPreferenceDialogFragment.java
│ │ │ │ ├── RadioListPreferenceDialogFragment.java
│ │ │ │ ├── StringListPreference.java
│ │ │ │ └── StringListPreferenceDialogFragment.java
│ │ │ ├── main/
│ │
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: # yuliskov
patreon: smarttube
open_collective: # smarttubeapp
ko_fi: # smarttube
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # smarttube
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
================================================
FILE: .github/ISSUE_TEMPLATE/1-bug_report.yml
================================================
name: Bug Report
description: Create a bug report to help us improve
title: "[BUG]: "
labels: [bug]
body:
- type: markdown
attributes:
value: |
Thank you for helping to make SmartTube better by reporting a bug.
Please fill in as much information as possible about your bug.
- type: checkboxes
id: checklist
attributes:
label: "Checklist"
options:
- label: "I made sure that there are *no existing issues* - [open](https://github.com/yuliskov/SmartTube/issues) or [closed](https://github.com/yuliskov/SmartTube/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to."
required: true
- label: "I have read the [FAQ](https://github.com/yuliskov/SmartTube#faq) and my problem isn't listed."
required: true
- label: "I have taken the time to fill in all the required details. I understand that the bug report will be dismissed otherwise."
required: true
- label: "This issue contains only one bug."
required: true
- type: input
id: app-version
attributes:
label: Affected version
description: "In which SmartTube version did you encounter the bug?"
placeholder: "x.xx.x - Can be seen in the app from the 'About' section in Settings"
validations:
required: true
- type: dropdown
id: device-type
attributes:
label: Device Type
description: Is it Smart TV/Box or Phone
options:
- "Smart TV/Box"
- "Phone/Tablet"
validations:
required: true
- type: input
id: device-os-info
attributes:
label: Affected Android
description: |
With what operating system (+ version) did you encounter the bug?
placeholder: "Example: Android TV 10"
validations:
required: true
- type: textarea
id: steps-to-reproduce
attributes:
label: Steps to reproduce the bug
description: |
What did you do for the bug to show up?
If you can't cause the bug to show up again reliably (and hence don't have a proper set of steps to give us), please still try to give as many details as possible on how you think you encountered the bug.
placeholder: |
1. Go to '...'
2. Press on '....'
validations:
required: true
- type: textarea
id: actual-behavior
attributes:
label: Actual behavior
description: |
Tell us what happens with the steps given above.
- type: textarea
id: additional-information
attributes:
label: Additional information
description: |
Any other information you'd like to include, for instance that
* Device (NVIDIA Shield, Xiaomi Mi Box, etc)
* screenshot
* your cat disabled your network connection
* ...
================================================
FILE: .github/ISSUE_TEMPLATE/2-feature-request.yml
================================================
name: Feature Request
description: Create a feature request for SmartTube
title: '[Feature Request]: '
labels: ['enhancement']
body:
- type: markdown
attributes:
value: Thanks for taking the time to file a feature request! Please fill out this form as completely as possible.
- type: textarea
attributes:
label: Describe the feature you'd like to request
description: A clear and concise description of what you want and what your use case is.
validations:
required: true
- type: textarea
attributes:
label: Describe the solution you'd like
description: A clear and concise description of what you want to happen.
validations:
required: true
- type: textarea
attributes:
label: Describe alternatives you've considered
description: A clear and concise description of any alternative solutions or features you've considered.
validations:
required: true
- type: textarea
id: additional-information
attributes:
label: Additional information
description: |
Any other information you'd like to include, for instance
* Relevant issues
* Mockup images
* The feature would make your cat happy
* ...
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
- name: Telegram group (international)
url: http://t.me/SmartTubeEN
about: "The international group is in **English only**. But don't worry if your English is not perfect, we have a friendly international community."
- name: Telegram group (RU/UA)
url: http://t.me/SmartTubeUA
about: "Group for Russian and Ukrainian speakers."
================================================
FILE: .github/workflows/CI.yml
================================================
name: Build Debug APK
on:
push:
branches: [ "master" ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
env:
HAS_SIGNING_KEY: ${{ secrets.SIGNING_KEY != '' }}
HAS_VT_KEY: ${{ secrets.VIRUS_TOTAL_API_KEY != '' }}
steps:
- name: Checkout Code
uses: actions/checkout@v6
with:
submodules: recursive
- name: Set up JDK 17
uses: actions/setup-java@v5
with:
java-version: '17'
distribution: 'temurin'
cache: 'gradle'
- name: Update Version Name
id: get_version
run: |
# Keep the original code to make the nightly and original builds interchangeable
sed -i "s/versionName \"\(.*\)\"/versionName \"\1-nightly-${{ github.run_number }}\"/" smarttubetv/build.gradle
echo "VERSION_NAME=$(grep "versionName" smarttubetv/build.gradle | head -n 1 | awk -F'"' '{print $2}')" >> $GITHUB_OUTPUT
- name: Configure Build Signing
if: ${{ env.HAS_SIGNING_KEY == 'true' }}
run: |
echo "storePassword=${{ secrets.KEY_STORE_PASSWORD }}" > keystore.properties
echo "keyAlias=${{ secrets.ALIAS }}" >> keystore.properties
echo "keyPassword=${{ secrets.KEY_PASSWORD }}" >> keystore.properties
echo "storeFile=${{ github.workspace }}/key.jks" >> keystore.properties
echo "${{ secrets.SIGNING_KEY }}" | base64 --decode > ${{ github.workspace }}/key.jks
- name: Grant Gradle permissions
run: chmod +x gradlew
- name: Lint with Gradle
run: ./gradlew lintStbetaRelease
- name: Upload Lint Report
uses: actions/upload-artifact@v7
if: always()
with:
name: lint-report
path: '**/build/reports/lint-results-*.html'
if-no-files-found: warn
- name: Build with Gradle
run: ./gradlew clean assembleStbetaRelease
- name: VirusTotal Scan
if: ${{ env.HAS_VT_KEY == 'true' }}
id: vt
uses: crazy-max/ghaction-virustotal@v5
with:
vt_api_key: ${{ secrets.VIRUS_TOTAL_API_KEY }}
files: |
./smarttubetv/build/outputs/apk/stbeta/release/*.apk
request_rate: 4
- name: VirusTotal Summary
if: steps.vt.outcome == 'success'
run: |
echo "Waiting 150s for VirusTotal engines to report..."
sleep 150
echo "### Security Scan Results" >> $GITHUB_STEP_SUMMARY
echo "| Artifact Name | VirusTotal Status | Detailed Report |" >> $GITHUB_STEP_SUMMARY
echo "| :--- | :--- | :--- |" >> $GITHUB_STEP_SUMMARY
for apk in ./smarttubetv/build/outputs/apk/stbeta/release/*.apk; do
filename=$(basename "$apk")
sha256=$(sha256sum "$apk" | awk '{print $1}')
# Construct the dynamic badge URL using the hash
badge_url="https://badges.cssnr.com/vt/id/$sha256?start=green&end=red&n=8"
vt_link="https://www.virustotal.com/gui/file/$sha256"
echo "| $filename | []($vt_link) | [View Report]($vt_link) |" >> $GITHUB_STEP_SUMMARY
done
- name: Upload ARM64 APK
uses: actions/upload-artifact@v7
with:
name: SmartTube_${{ steps.get_version.outputs.VERSION_NAME }}_arm64
path: ./smarttubetv/build/outputs/apk/stbeta/release/*_arm64-v8a.apk
if-no-files-found: error
- name: Upload ARMv7 APK
uses: actions/upload-artifact@v7
with:
name: SmartTube_${{ steps.get_version.outputs.VERSION_NAME }}_armeabi-v7a
path: ./smarttubetv/build/outputs/apk/stbeta/release/*_armeabi-v7a.apk
if-no-files-found: error
- name: Upload Universal APK
uses: actions/upload-artifact@v7
with:
name: SmartTube_${{ steps.get_version.outputs.VERSION_NAME }}_universal
path: ./smarttubetv/build/outputs/apk/stbeta/release/*_universal.apk
if-no-files-found: error
- name: Upload x86 APK
uses: actions/upload-artifact@v7
with:
name: SmartTube_${{ steps.get_version.outputs.VERSION_NAME }}_x86
path: ./smarttubetv/build/outputs/apk/stbeta/release/*_x86.apk
if-no-files-found: error
================================================
FILE: .github/workflows/cleanup.yml
================================================
name: Cleanup old workflow runs
on:
schedule:
- cron: '0 3 * * *'
workflow_dispatch:
jobs:
cleanup:
runs-on: ubuntu-latest
if: github.event.repository.fork == false
permissions:
actions: write
steps:
- uses: actions/github-script@v8
with:
script: |
const KEEP = 0;
const workflowNames = ["VirusTotal Scan", "Cleanup old workflow runs"];
// Get workflow ID
const workflows = await github.rest.actions.listRepoWorkflows({
owner: context.repo.owner,
repo: context.repo.repo
});
for (const name of workflowNames) {
const wf = workflows.data.workflows.find(w => w.name === name);
if (!wf) {
core.info(`Workflow "${name}" not found, skipping`);
continue;
}
// List runs
const runs = await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: wf.id,
per_page: 100
});
const toDelete = runs.data.workflow_runs.slice(KEEP);
core.info(`Deleting ${toDelete.length} old runs`);
for (const run of toDelete) {
try {
await github.rest.actions.deleteWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: run.id
});
} catch (e) {
core.info(`Skip run ${run.id}: ${e.message}`);
}
}
}
================================================
FILE: .github/workflows/stale.yml
================================================
name: "Close stale issues"
on:
workflow_dispatch:
branches:
- master
jobs:
stale:
runs-on: ubuntu-latest
permissions:
contents: read
actions: write
issues: write
steps:
- uses: actions/stale@v10
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
operations-per-run: 3000 # This may result in rate limiting, could we reduce and run in batches?
days-before-stale: 420 # 1st Jan 2025, as of 25th Feb 2026
days-before-close: 0
ignore-updates: true
stale-issue-message: ''
close-issue-message: |
**Due to a high volume of stale issues, all issues older than January 1st 2025 are being closed automatically.**
Please feel free to resubmit your issue if you believe it has not been appropriately dealt with, and tag this issue in the "Additional Information" section.
================================================
FILE: .github/workflows/virustotal_scan.yml
================================================
name: VirusTotal Scan
on:
release:
types: [published]
workflow_dispatch:
inputs:
release_tag:
description: 'Release tag to scan'
required: true
jobs:
virustotal_scan:
permissions:
contents: write
runs-on: ubuntu-latest
env:
HAS_VT_KEY: ${{ secrets.VIRUS_TOTAL_API_KEY != '' }}
steps:
- name: Set tag variable
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "TAG_NAME=${{ github.event.inputs.release_tag }}" >> $GITHUB_ENV
else
echo "TAG_NAME=${{ github.event.release.tag_name }}" >> $GITHUB_ENV
fi
- name: Set report marker variable
run: |
echo -e "MARKER=\t\t\t" >> $GITHUB_ENV
- name: Checkout code
uses: actions/checkout@v6
- name: Download Release Assets
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
mkdir -p release_assets
gh release download "$TAG_NAME" --dir release_assets --pattern "*.apk"
- name: VirusTotal Scan
if: ${{ env.HAS_VT_KEY == 'true' }}
id: vt
uses: crazy-max/ghaction-virustotal@v5
with:
vt_api_key: ${{ secrets.VIRUS_TOTAL_API_KEY }}
files: |
release_assets/*.apk
request_rate: 4
- name: Generate Custom Badge Report
if: steps.vt.outcome == 'success'
run: |
echo "Waiting 150s for VirusTotal engines to report..."
sleep 150
echo -e "$MARKER\n## 🛡️ VirusTotal Analysis" > vt_report.txt
echo "" >> vt_report.txt
echo "| Build Variant | VirusTotal Status | Detailed Report |" >> vt_report.txt
echo "| :--- | :--- | :--- |" >> vt_report.txt
for file in release_assets/*.apk; do
[ -e "$file" ] || continue
filename=$(basename "$file")
sha256=$(sha256sum "$file" | awk '{print $1}')
vt_link="https://www.virustotal.com/gui/file/$sha256/detection"
badge_url="https://badges.cssnr.com/vt/id/$sha256?start=green&end=red&n=8"
echo "Purging badge cache for $filename..."
curl -s -X POST $badge_url
asset_link="https://github.com/${{ github.repository }}/releases/download/${{ env.TAG_NAME }}/$filename"
echo "| [$filename]($asset_link) | [)]($vt_link) | [View Report]($vt_link) |" >> vt_report.txt
done
- name: Update Release Notes
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release view "$TAG_NAME" --json body -q .body > current_notes.txt || echo "" > current_notes.txt
# If the header exists, delete from that line to the end
if grep -q "$MARKER" current_notes.txt; then
echo "Previous report found. Cleaning up..."
sed -i "/$MARKER/,\$d" current_notes.txt
fi
{
cat current_notes.txt
cat vt_report.txt
} > final_notes.txt
gh release edit "$TAG_NAME" --notes-file final_notes.txt
================================================
FILE: .gitignore
================================================
# built application files
*.apk
*.ap_
# files for the dex VM
*.dex
# Java class files
*.class
# generated files
bin/
gen/
# Local configuration file (sdk path, etc)
local.properties
# Windows thumbnail db
Thumbs.db
# OSX files
.DS_Store
# Eclipse project files
.classpath
.project
# Android Studio
.idea
*.iml
#.idea/workspace.xml - remove # and delete .idea if it better suit your needs.
.gradle
.google
build/
# my other stuff
/smartyoutubetv2/release
/smarttube/release
/smarttubetv/release
# gradle 6 fix
/smarttube/output
/smarttubetv/output
/smarttubemobile/release
# google-services.json
*.hprof
log.txt
android.keystore
android-upd2.keystore
build.log
notes.txt
out.txt
out1.txt
deps.txt
logcat.txt
/releases
/files
/misc
/other
/TODO.txt
tmp/
*_bak*
*_tmp
*.bak*
*.tmp
*.7z
.DS_Store
/captures
.externalNativeBuild
fabric.properties
*BAK.java
hs_err_pid*.log
================================================
FILE: .gitmodules
================================================
[submodule "SharedModules"]
path = SharedModules
url = https://github.com/yuliskov/SharedModules
[submodule "MediaServiceCore"]
path = MediaServiceCore
url = https://github.com/yuliskov/MediaServiceCore
================================================
FILE: .reuse/dep5
================================================
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: SmartTube
Source: https://github.com/yuliskov/SmartTube
Files: *
Copyright: 2020-present yuliskov
License: MIT
License: MIT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2020-present yuliskov
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
<p align="center">
<a href="https://f-droid.org/packages/app.smarttube.fdroid/">
<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on-en.svg" alt="Get it on F-Droid" width="206" style="max-width:100%; height:auto;"/>
</a>
</p>
# Important announcement about the app
My development environment was infected by unknown malicious software, as a result of which a few builds may have been affected. Once the issue was detected, I secured everything with a full disk wipe, restored a clean setup, and now all builds are scanned with VirusTotal. The F-Droid version will also be verified before release.
Public keys may have been compromised, which is why I am sharing this issue. You can download the new version and the new public key below, and instructions for restoring backups are provided.
No extra actions are required since the app uses **one-time connection codes**. These codes have very limited permissions (for example, they cannot change your password). Still, you can revoke them if you want full peace of mind.
# How to revoke access:
1. Open [myaccount.google.com/security](https://myaccount.google.com/security)
2. Find **“Your connections to third-party apps & services”**
3. Tap **“See all connection”** and locate **YouTube TV** or **Google Drive**
4. Select the app → **“Remove access”**
Please keep built-in security features enabled to stay protected.
# SmartTube
<!-- <img width="100" src="https://github.com/yuliskov/SmartTube/blob/master/smarttubetv/src/ststable/res/mipmap-nodpi/app_icon.png" alt="logo"/> -->

SmartTube is a free and open-source advanced media player for Android TVs and TV boxes. It allows you to play content from various public sources.
### ✅ Features
- No ads
- SponsorBlock integration
- Adjustable playback speed
- 8K resolution support
- 60fps playback
- HDR compatibility
- View live chat
- Customizable buttons
- Does not require Google Services
- Helpful international community
### ❌ Limitations
- Not supported on phones and tablets
- Comment functionality is unstable
- Voice search and casting performance may be inferior to official apps, depending on your device
Give it a try!
**Do you have any question?** Ctrl+F or ⌘F this readme first!
[**Installation**](#installation) | [**Official Site**](https://smarttubeapp.github.io) | [**Donation**](#donation) | [**FAQ**](#faq) | [Support / Chat](#support) | [Build](#build) | [Translate the app](https://jtbrinkmann.de/tools/android-strings.xml-translator.html) | [Changelog](https://t.me/s/SmartTubeNewsEN) | [Liability](#liability)
## Device support
> [!IMPORTANT]
> Starting in October 2025 new Amazon FireTV devices no longer run Android under the hood. SmartTube will **not** be compatibile with the Fire Stick 4k Select and newer devices which run Amazon's own VegaOS.

* **Supported:** all Android TVs and TV boxes (incl. All FireTV devices released before Oct. 2025, NVIDIA Shield & Chromecast with Google TV), even older ones with Android 4.3 (Kitkat).
* **Not supported:** Smartphones, non-Android platforms like Samsung Tizen, LG webOS, Apple TV, etc.
## Installation
> [video of the installation](images/new/zPV0imF.mp4) (note: download url changed to `kutt.to/stn_beta` or `kutt.to/stn_stable`)
**Do not** download SmartTube from any **app store**, APK websites or blogs; these were uploaded by other people and may contain malware or ads. SmartTube is not officially published on any app store. Sadly, the Google PlayStore does not allow ad-free Youtube apps using unofficial APIs.
There is a **beta release** (recommended) and a **stable release**. Beta gets new features and bugfixes faster than the stable release.
You can use either of the following methods to install the app:
- (**Easiest**) Install [Downloader by AFTVnews](https://www.aftvnews.com/downloader/) on your Android TV, open it and enter `kutt.to/stn_beta` or `kutt.to/stn_stable`, then read, understand and confirm the security prompts. (<small>You can also enter [**79015**](https://aftv.news/79015) (for beta) or [**28544**](https://aftv.news/28544) (for stable), but this requires an extra step to install the AFTVnews Downloader browser addon if you haven't already.</small>)
- Install a file transfer app on your Android TV, download the APK on your phone or computer and transfer it to your TV (e.g. [_Send Files to TV_](https://sendfilestotv.app/) from the Google Play Store / Amazon AppStore)
- Download the APK onto a USB stick, put the USB stick into your TV and use a file manager app from the Google Play Store / Amazon AppStore (e.g. [_FX File Explorer_](https://play.google.com/store/apps/details?id=nextapp.fx) or [_X-plore_](https://play.google.com/store/apps/details?id=com.lonelycatgames.Xplore)). Android's preinstalled file manager does not work! Do **not** get the ad-infested _FileCommander_.
- If you are an advanced user, you can install it using ADB. [guide](https://fossbytes.com/side-load-apps-android-tv/#h-how-to-sideload-apps-on-your-android-tv-using-adb) | [alternative guide](https://www.aftvnews.com/sideload/)
**Troubleshooting:** See device specific notes below. If installation fails, either your **disk space is full** or the APK file didn't download correctly; clear up space and try downloading again. If the app installed, but crashes when opening, make sure to install it to internal memory, not to an SD card / external storage.
**The app has a built-in updater** with changelog. You can also find all releases and the **changelog** on the [Telegram channel @SmartTubeNewsEN](https://t.me/s/SmartTubeNewsEN) (readable without account) or on [Github](https://github.com/yuliskov/SmartTube/releases/).
> latest [**beta download**](https://github.com/yuliskov/SmartTube/releases/download/latest/smarttube_beta.apk)
>
> latest [stable download](https://github.com/yuliskov/SmartTube/releases/download/latest/smarttube_stable.apk)
### Installation (Chromecast with Google TV)
On **Chromecast with Google TV**, installation of apps is blocked by default, so an extra step is required:
> **4.1. Enable Developer Options**
>
> On your Chromecast, open the side menu and go to _Settings > System > About_. Scroll down to the _Android TV OS build_ section and click that repeatedly. A toast message will appear, explaining that you are a few steps away from being a developer. Continue clicking until you trigger it.
>
>
> **4.2. Turn on the "unknown sources" setting**
>
> Go back to the main _Settings_ page and select _Apps > Security & Restrictions > Unknown sources_. Turn on the toggle for \[_Downloader by AFTVnews_ or\] whichever file browser you decided to use [...].
>
> [[source & picture guide](https://www.androidpolice.com/2021/02/07/how-to-sideload-any-apk-on-the-chromecast-with-android-tv/#install-the-apk)]
After this, you can follow the [general installation guide](#installation) above.
### Installation (Xiaomi devices with Chinese firmware)
Xiaomi's **Chinese firmware** might block the installation **of the beta version**. The international firmware is not affected. Solutions:
1. Use SmartTube's **stable version** instead (**recommended**)
2. Use the international firmware for your device
3. (if your device is from 2020 or before) You can do a factory reset and then install SmartTube beta before doing any system updates. You can then safely update your system, SmartTube should continue working.
### Updating
The app has a built-in updater. You only need to follow the installation procedure **once**. A few seconds after launching SmartTube, it will notify you if there is any update and also show a changelog. You can disable automatic update checks or manually update in the settings under "about".
If the installation fails, either your **disk space is full** or the update didn't download correctly; clear up space and try updating again (_Settings > About > Check for updates_).
## Compatibility
SmartTube requires Android 4.3 or above. It does not work on non-Android devices (incl. LG or Samsung TVs). On unsupported TVs, you can use a TV stick or TV box. Though this app technically runs on smartphones and tablets, it is not optimized for such and offers no official support!
It has been successfully tested on TVs, TV boxes and TV sticks that are based on Android, including:
- Android TVs & Google TVs (e.g. Philips, Sony)
- Chromecast with Google TV & TVs with _Chromecast built-in_
- Amazon FireTV stick (all generations)
- NVIDIA Shield
- TV boxes running Android (many cheap chinese no-name boxes)
- Xiaomi Mi Box
## Features
### Adblocking
SmartTube does not show any ad banners, preroll ads or ad intermissions. It not just tries to prevent them, it is literally programmed to be completely **unable** to display any ads, so YouTube cannot slip anything in. This also means you cannot allow ads or whitelist channels. Some YouTube channels include sponsored messages in their videos, these can also be skipped, see [SponsorBlock](#SponsorBlock) below.
### SponsorBlock
SmartTube includes a SponsorBlock integration. From the [SponsorBlock website](https://sponsor.ajay.app/):
> SponsorBlock is an open-source crowdsourced browser extension and open API for **skipping sponsor segments** in YouTube videos. [...] the extension automatically skips sponsors **it knows about** using a privacy preserving query system. It also supports skipping **other categories**, such as intros, outros and reminders to subscribe [and non-music parts in music videos].
You can select which categories you want to skip in the settings. Unlike the browser addon, in SmartTube you cannot submit new segments (TVs and TV remotes aren't great devices for such precise operations). Note that SponsorBlock is a free and voluntary project based on user submissions, so don't expect it to 100% work every time. Sometimes, sponsor segments are not yet submitted to the database, sometimes the SponsorBlock servers are offline/overloaded.
### Casting
To cast videos from your phone (or other devices), you must link that device to your TV. Unlike the original YouTube app, SmartTube does not automatically show up when you are in the same wifi network. How to link your smartphone and TV:
1. open SmartTube and go to settings
2. go to "Remote control" (2nd option)
3. open your YouTube app on your phone, go to settings > General > watch on TV
4. click on _connect using TV-code_ and enter the code from your TV
[**Screenshot guide**](https://t.me/SmartTubeEN/8514)
Due to technical limitations, you need to open the app on the TV before casting; SmartTube cannot automatically wake up the TV.
### Picture-in-Picture (PiP)
SmartTube supports playing videos in PiP mode. This needs to be enabled under _Settings > General > Background playback > Picture in picture_. The video will go into PiP mode when you press home while playing a video, and also when you press _back_ if enabled in _Settings > General > Background playback (activation)_.
### Adjust Speed
You can adjust the playback speed pressing the speed-indicator icon (gauge) in the top row of the player. This is remembered across videos. Some speeds may case frame drops, this is a known issue.
### Voice Search
To enable global voice search, an additional app must be installed alongside SmartTube. This _bridge app_ can intercept the System's attempts to open the original YouTube app and open SmartTube instead. For this to work, you must uninstall the original YouTube app. We know this sucks, but you can always reinstall it if you change your mind. The _bridge app_ will not show up in your launcher and you cannot launch it directly; it is only used internally by the system's voice search. On some devices, you need to explicitly say "Youtube" when searching (e.g. say "youtube cute cats" instead of just "cute cats").
**On Amazon Fire TV**:
1. Uninstall the original YouTube app (no root required)
2. Download and install the Amazon Bridge SmartTube app: https://kutt.to/stn_bridge_amazon (e.g. via _Downloader by AFTVnews_)
**On Google Chromecast with Google TV**:
1. Uninstall the original YouTube app (no root required)
2. Download and install the ATV Bridge SmartTube app: https://kutt.to/stn_bridge_atv (e.g. via _Downloader by AFTVnews_)
**On all other Android devices**, sadly root is required to enable this:
1. Root your device (search for a guide for your specific device)
2. Uninstall the official YouTube app using root (`adb shell pm uninstall com.google.android.youtube.tv`)
3. Download and install the ATV Bridge SmartTube app: https://kutt.to/stn_bridge_atv (e.g. via _Downloader by AFTVnews_)
## Donation
If you want to support my developments you are welcome to buy me a cup of coffee :)
- [**Patreon (Visa, Mastercard, PayPal)**](https://www.patreon.com/smarttube)
- **PayPal**: firsth<!-- abc@def -->ash@gmai<!-- @abc.com -->l.com
<!-- > [**Buy me a coffee**](https://www.buymeacoffee.com/stube) -->
- **BTC**: 1JAT5VVWarVBkpVbNDn8UA8HXNdrukuBSx
- **LTC**: ltc1qgc24eq9jl9cq78qnd5jpqhemkajg9vudwyd8pw
- **ETH**: 0xe455E21a085ae195a097cd4F456051A9916A5064
- **ETC**: 0x209eCd33Fa61fA92167595eB3Aea92EE1905c815
- **TRX**: TJNPY794aSGZf3WGHTna2VCWm2G5Yua7E8
- **USDT (TRC20)**: TJNPY794aSGZf3WGHTna2VCWm2G5Yua7E8
- **USDT (BEP20)**: 0x64B28da787BE6ac5889D276A5638d4f077840eC5
- **USDT (ERC20)**: 0xe455e21a085ae195a097cd4f456051a9916a5064
- **TON**: UQAc9zgnnzwS8yb5wxAu5CB0RddmjPBjWI-n46oQ7XfCQrgI
- **XMR**: 48QsMjqfkeW54vkgKyRnjodtYxdmLk6HXfTWPSZoaFPEDpoHDwFUciGCe1QC9VAeGrgGw4PKNAksX9RW7myFqYJQDN5cHGT
## Support
**Please check the [FAQ](#faq) first!** Also at least have a short look at the recent chat history.
You can report in our Telegram group or via [issue tracker on Github](https://github.com/yuliskov/SmartTube/issues) (account required).
- **Telegram group (international)**: [@SmartTubeEN](http://t.me/SmartTubeEN)
- **Discord group (international)**: [SmartTube Official](https://discord.gg/Wt8HDDej5z)
- **Telegram group (RU/UA)**: [@SmartTubeUA](http://t.me/SmartTubeUA)
- **Email**: firsth<!-- abc@def -->ash@gmai<!-- @abc.com -->l.com
The international group is in **English only**. But don't worry if your English is not perfect, we have a friendly international community.
## Team
SmartTube is developed single-handedly; there is no larger team or company behind this. This is an open source, hobby project. Several others have helped with translations, some of which can be seen on [Github](https://github.com/yuliskov/SmartTube/graphs/contributors), some have sent their translations directly to Yurii. There are also helpful people in the support chat.
## Build
**NOTE: OpenJDK 14 or older (!) is required. Newer JDK could cause app crash!**
To build and install debug version, run these commands:
```
git clone https://github.com/yuliskov/SmartTube.git
cd SmartTube
git submodule update --init
adb connect <device_ip_address>
gradlew clean installStstableDebug
```
## Video codecs
Video codecs are the algorithms used for video compression.
### Which codec to choose / overview
| | recommendation | hardware support | compression, bitrate\* | quality |
|:--------:|:---------------------------------------------|:---------------------------- |:----------------------:|:-------:|
| **AV01** aka. AV1 | best choice, **if your device supports** | first devices started coming in **2020** | **best** <small>(e.g. 1.6 Mbps)</small> | same |
| **VP9** | **best choice on most devices** | most devices **since 2015** | **better** <small>(e.g. 2.1 Mbps)</small> | same |
| AVC | only for old or slow hardware | **all** devices | good <small>(e.g. 2.7 Mbps)</small> | same |
<small>\* Examples taken from the video-only track at 1080p @ 25fps for this video: [Dua Lipa - New Rules (Official Music Video)](https://youtube.com/watch?v=k2qgadSvNyU)</small>
At the same resolution, a **lower bitrate is better!** YouTube explicitly targets the **same quality** regardless of the codec. Older codecs have a higher bitrate only because they are less efficient. On Youtube, you **do not** get better quality by simply choosing a higher bitrate. Newer codecs have a better compression = lower bitrate = use less bandwidth = save the environment. This is a feature, not a bug. You should use the newest codec that works smoothly on your device, not the least efficient one. AVC usually has the highest bitrate. This is bad, not good.
### Which quality to choose?
Currently, there is no automatic mode based on your bandwidth. But you can configure a default video preset yourself under settings \> video player \> video presets. The first option ("none") will remember your last selection within the video player. Any other preset is used initially for each video; if the selected profile is not available, the next best available option is used. You can still override the profile on each video individually within the player.
To decide the optional resolution / video quality for you, you need to consider a few limiting factors:
- Your bandwidth (choose only up to the bitrate that your bandwidth can handle; you can do a speedtest using [fast.com](https://fast.com) by Netflix)
- Your TV's display resolution (the quality **might slightly** improve, if you select the next higher resolution, e.g. 1080p on a 720p display; but don't expect a big difference)
- Your TV's capabilities (e.g. HDR, 60fps)
Generally 60fps is an improvement, but if you personally don't notice (or mind) the difference, you can save bandwidth (and the environment) by not choosing 60fps.
### HDR
HDR works only **if your hardware supports it**. It's a complicated mess:
- Your TV must support it
- If you use a TV box, that TV box **and** your TV cable **and** the TV must support HDR
- Yes, there truly are different HDMI cable versions with different HDR-support, it's complicated
- some devices (like the **NVIDIA Shield**) generally support HDR, but **not** the specific HDR format that is used on YouTube :cry:
If HDR videos look looked dim or washed out, then check [this article](https://www.wired.com/story/hdr-too-dark-how-to-fix-it/). **If HDR is not working**, it's probably not this app's fault. You might need to search on the web for "HDR" and your device name for any help.
## Liability
We take no responsibility for the use of our tool, or external instances
provided by third parties. We strongly recommend you abide by the valid
official regulations in your country. Furthermore, we refuse liability
for any inappropriate use of Invidious, such as illegal downloading.
This tool is provided to you in the spirit of free, open software.
You may view the LICENSE in which this software is provided to you [here](./LICENSE).
> 16. Limitation of Liability.
>
> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
## FAQ
### Q: Videos buffer a LOT
A: Try to switch to encrypted DNS like NextDNS. You can set-up such DNS either automatically or manually. To automatic set-up you can use the [Intra apk at fdroid](https://f-droid.org/en/packages/app.intra/) and the ["AutoStart - No root"](https://play.google.com/store/apps/details?id=com.autostart) apk to make it autolaunch after every TV restart. For manual set-up [use this guide](https://www.reddit.com/r/MiBox/s/7esEVGtAAa).
### Q: There is no result for the search that I say (Android 11)
A: They're some reports that the latest update for "Google app for Android TV" could cause this bug. Deleting the update should fix the problem.
### Q: AV01 does not play / Why is VP9 slow on my device?
A: Because AV01 is very new, **most** TVs and TV boxes **do not** offer hardware support and **cannot** play AV01 **at all**.
If your device has hardware support for a codec, videos using that codec should play smoothly. High resolutions might also be slow in VP9 on cheap TV boxes that don't officially support 4k. Your device probably can play VP9 videos even without hardware support, however this requires a powerful CPU to run smoothly. Fixing AV01 without hardware support is technically possible, but currently not planned and probably not efficient enough.
### Q: Can you make SmartTube look like the original app?
A: Compared to SmartTube's UI, Stock Youtube and YT Kids are far ahead. However, we'd need someone who's skilled and willing to dedicate enough time and energy into making it. And into maintaining it longterm (incl. new features, bug fixes). All of this for free. If you are / got someone like that, please help.
Not to mention that SmartTube follows Google's official template & recommendations for Android TV apps. It's Google's fault that the template is somewhat ugly. 😂
### Q: Can the search page be improved?
A: It can be, but it takes someone to do it, similar to the above FAQ-entry. SmartTube is following Google's officially recommended design/template for TV apps and is using the official, preinstalled Android TV keyboard. Sadly, Google did a really bad job regarding the search page and keyboard. Maybe a future SmartTube update can add an embedded keyboard, similar to the original YouTube or other major Android TV apps. Maybe it can improve the looks to be as good or better than in the official YouTube app. But for now, it is the way it is due to lack of time and due to Google's official recommendations being bad.
### Q: Can I install this on a Samsung Tizen TV / LG webOS TV / Roku / iOS / toaster?
A: No, this only works on **Android** devices. If you look at an Android TV's product page, it usually says clearly that it's based on Android. The app **cannot** easily be ported over to other plattforms and we have no plans to even try. **Please do not ask**. Instead, you can connect a separate TV stick or TV box to your TV.
### Q: Can I install this on a smartphone? / Can you add portrait mode? / Scrolling doesn't work.
A: **Big No**. This app is **not** for smartphones, we offer **zero support** for that.
You **can cast** videos **from** your smartphone to a TV / TV box running SmartTube, though. Just use the official YouTube app or [ReVanced](https://github.com/ReVanced), see [the casting section](#casting) for more information.
**There will not be a phone version.** You can use [ReVanced](https://github.com/ReVanced), [Pure Tuber](https://play.google.com/store/apps/details?id=free.tube.premium.advanced.tuber), [NewPipe](https://newpipe.schabi.org), or [NewPipe x SponsorBlock](https://github.com/polymorphicshade/NewPipe#newpipe-x-sponsorblock) instead. Please go to their respective support chats for help.
### Q: Can I install this on a tablet / car screen / smartphone with docking station?
Yes... maybe.. Requirements:
- It is an Android device
- It has a large screen
- It has a TV remote, controller, or keyboard
**Touch input is not supported.** Mouse/touchpad scrolling neither. You cannot properly use SmartTube with only touch or mouse input.
Some users reported great success (incl. on a [car entertainment system](https://t.me/SmartTubeEN/6060)). **Please share your success stories with us.**
### Q: I get "unknown codec" / "can't download video" errors
A: please wait 5 seconds for the video to play. If that doesn't help, press the play button. Some users reported, that this issue only appears when they have a USB audio device attached or if their disk storage is full.
### Q: I get "the video profile is not supported"
A. Press the "HQ"-button in the bottom-left, select _video formats_ and select anything other than AV01. AV01 is **not supported** on most devices (apparently including yours), so select VP9 instead. See [the section on video codecs](#Video-codecs) for more information.
### Q: I get "video unavailable" when watching unlisted videos / my own videos
A: Right, that's currently a bug.
### Q: It doesn't show up on my casting list
A: Please read the [Casting](#casting) section.
### Q: I get an error saying "Sign in to confirm you're not a bot"
A: Your IP address range might be temporaily/permanently blocked by YouTube from watching videos if you not signed in to your account.
### Q: The video is buffering a lot
A: The issue might not be specific to SmartTube, as other unofficial YouTube apps also report this issue. It seems uncommon nowadays, but was very present in the 2nd quarter of 2021. Some users or devices seem to be more affected then others. The official YouTube app & website are apparently only rarely affected. The root cause of the issue is currently unclear, but it appears to be a server-side thing on YouTube's end. Possibly, YouTube is discriminating 3rd party apps.
For now, try to see if it helps to:
- Reduce the resolution (or chance it back)
- Change the video format to AVC
- Increase the buffer in the settings
- Hit the back button and try playing the video again
### Q: The debug information says my display is 1080p, but I have a 4k/UHD display!
A: Do not worry, **the debug information is incorrect.** SmartTube works fine even above 1080p and you should be able to see that, when you play a video in 4k or UHD.
Also do not worry if it says "720p" and you have a 1080p display.
### Q: Why does it not autoselect highest quality?
A: **It does** (by default). If you set a _video profile_ under settings, that acts as a maximum for automatic selection. Check if you configured a video profile, you can unset it by choosing "none".
**Please do not confuse quality with bitrate**. See [the section on video codecs](#Video-codecs) for more information.
### Q: Can I set a (maximum) resolution by default?
A: SmartTube automatically select the highest available quality for your video, up to a maximum resolution that you can set in the settings under "video profile". If available, SmartTube will pick the selected video profile, or otherwise the next best one available will be used. You can still always change the video profile while watching videos.
### Q: Can it set the resolution to "auto", depending on my available bandwidth?
A: This is planned, but not available yet (sorry 🙇♀️). However, you can set a maximum resolution to something that should work for your bandwidth. See above for details.
### Q: Why does it skip video segments?
A: SmartTube has a feature called **SponsorBlock**. You can select categories should be skipped, if any. See the [SponsorBlock section](#sponsorblock) for more details.
### Q: How to start the next video automatically / stop after every video?
A: You can switch between different autoplay-modes using the loop-button 🔁
[](https://t.me/SmartTubeEN/24953)
### Q: How to remove recommended videos (e.g. news) that are unrelated to me?
A: Recommended videos are defined by YouTube and not by the app, we cannot change the algorithm. They are based on your country, which you can change in the settings. If you are logged in, they are based on your watch history, user profile data, and whatever else Google might use. If you are not logged in, you are like in "incognito mode", so your watch history does not influence your recommendations. Maybe a future version will add optional user profiling without logging in.
### Q: Does HDR work?
A: Yes, HDR works **if your hardware** supports it. The **NVIDIA Shield** does not. See [the section on HDR](#HDR) for more information.
### Q: Why do some updates say "don't update if satisfied with the current version" in the changelog?
A: These updates change a lot of code, trying to fix bugs that only affect a few users/devices. Only the affected users should update. For anyone else, there is nothing to gain from updating; however there is the chance of causing new bugs. Do not worry if you updated anyways.
### Q: When playing at other speeds, frames are skipped!
A: We currently cannot fix this, sorry.
### Q: What is AFR?
A: "Auto Frame Rate". It adjusts the refresh rate of your TV to match the content you're watching. It can slightly improve the smoothness, but the difference is very small; most people barely notice it. It does not work well on every hardware. If you don't know what it does and don't want to test it out yourself, you can safely keep it off.
**Recommendation:** You can turn it on to see if it works on your device; if it causes issues (or if you don't care to test), turn it **off**.
### Q: Should I choose high or low buffer?
A: The higher your buffer, the more of a video will be preloaded ahead of your current position. A low buffer might minimally reduce your bandwidth usage, if you often close videos before they end. A high buffer can smooth out network issues and prevent the video from pausing to buffer. A higher buffer increases RAM usage, however this shouldn't be an issue.
**Recommendation: high**.
### Q: Can I retain the buffer when seeking back?
A: No, when you seek back (e.g. jump back 5 seconds), SmartTube will have to rebuffer. This might be improved in a future update.
### Q: My device freezes when watching YouTube
A: That's a firmware or Android issue. If you are using a custom rom, maybe that rom is buggy. Because this issue is nearly impossible for the developer to debug, we cannot help you, sorry. You can try the usual workarounds: rebooting, clearing cache, reinstalling the app, or factory resetting the device.
### Q: Can I download videos?
A: Not with SmartTube
### Q: Can updates be installed automatically?
A: No, this is technically not possible. Only the preinstalled app manager (usually Google PlayStore, Amazon AppStore, etc) has the required permission. All other apps, incl. SmartTube can only show open installation prompt. A workaround using root would be possible, but hasn't been implemented yet.
### Q: Can I whitelist ads on some channels?
A: No, this is not possible. SmartTube does not have any code to display ads. Adding this functionality would actually take time and effort, which is instead spent on adding useful features and fixing bugs.
================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.
apply from: gradle.ext.sharedModulesConstants
// NOT working
// Running 'gradle wrapper' will generate gradlew
wrapper {
gradleVersion = gradleVersion
distributionType = Wrapper.DistributionType.BIN
}
buildscript {
apply from: gradle.ext.sharedModulesConstants
repositories {
google()
mavenCentral()
// IntelliJ 'Read timed out' (error 403)
// https://stackoverflow.com/questions/74258160/is-jcenter-down-permanently-31-oct
//jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.4.2'
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:' + kotlinVersion
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
//flatDir { dirs 'libs' } // include duktape-my to all subprojects
// IntelliJ 'Read timed out' (error 403)
// https://stackoverflow.com/questions/74258160/is-jcenter-down-permanently-31-oct
//jcenter()
}
configurations.all {
// WorkManager conflict resolution
resolutionStrategy.force 'androidx.lifecycle:lifecycle-livedata-core:' + liveDataVersion
resolutionStrategy.force 'androidx.lifecycle:lifecycle-livedata:' + liveDataVersion
resolutionStrategy.force 'androidx.lifecycle:lifecycle-runtime:' + liveDataVersion
// Force Android 4 compatible okHttp version
resolutionStrategy.force 'com.squareup.okhttp3:okhttp:' + okhttpVersion
// Downgrade kotlin version for WorkManager
resolutionStrategy.force 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:' + kotlinVersion
resolutionStrategy.force 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:' + kotlinVersion
resolutionStrategy.force 'org.jetbrains.kotlin:kotlin-stdlib:' + kotlinVersion
resolutionStrategy.force 'org.jetbrains.kotlinx:kotlinx-coroutines-android:' + kotlinxVersion
resolutionStrategy.force 'androidx.core:core-ktx:' + kotlinCoreXVersion
resolutionStrategy.force 'androidx.core:core:' + coreXVersion
resolutionStrategy.force 'androidx.annotation:annotation:' + annotationXVersion
// Downgrade Cronet version for cronet-okhttp
resolutionStrategy.force 'org.chromium.net:cronet-api:' + cronetApiVersion
resolutionStrategy.force 'androidx.multidex:multidex:' + multiDexVersion
// Replace with modded library (leanback-1.0.0)
exclude group: 'androidx.leanback', module: 'leanback'
// Replace with modded library (fragment-1.1.0)
exclude group: 'androidx.fragment', module: 'fragment'
// Don't work! Replace with modded library (leanback-1.0.0)
// resolutionStrategy.dependencySubstitution {
// // substitute remote dependency with local module
// substitute module('androidx.leanback:leanback') using project(':leanback-1.0.0')
// }
}
}
================================================
FILE: chatkit/.gitignore
================================================
/build
================================================
FILE: chatkit/LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: chatkit/build.gradle
================================================
apply from: gradle.ext.sharedModulesConstants
apply plugin: 'com.android.library'
android {
compileSdkVersion project.properties.compileSdkVersion
buildToolsVersion project.properties.buildToolsVersion
defaultConfig {
minSdkVersion project.properties.minSdkVersion
targetSdkVersion project.properties.targetSdkVersion
versionCode 1
versionName '0.4.1'
consumerProguardFiles 'proguard.txt'
}
android {
lintOptions {
abortOnError false
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(':sharedutils')
implementation 'androidx.appcompat:appcompat:' + appCompatXVersion
implementation 'com.google.android.material:material:' + materialVersion
implementation "com.google.android.flexbox:flexbox:" + flexboxVersion
implementation 'androidx.recyclerview:recyclerview:' + recyclerviewXVersion
}
================================================
FILE: chatkit/proguard.txt
================================================
# ViewHolder constructors are resolved by reflection
-keepclassmembers class * extends com.stfalcon.chatkit.commons.ViewHolder {
public <init>(android.view.View);
}
================================================
FILE: chatkit/src/main/AndroidManifest.xml
================================================
<manifest package="com.stfalcon.chatkit">
</manifest>
================================================
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/DebouncedOnClickListener.java
================================================
package com.stfalcon.chatkit.commons;
import android.os.SystemClock;
import android.view.View;
import java.util.Map;
import java.util.WeakHashMap;
/**
* A Debounced OnClickListener
* Rejects clicks that are too close together in time.
* This class is safe to use as an OnClickListener for multiple views, and will debounce each one separately.
*/
public abstract class DebouncedOnClickListener implements View.OnClickListener {
private final long minimumIntervalMillis;
private final Map<View, Long> lastClickMap;
/**
* Implement this in your subclass instead of onClick
*
* @param v The view that was clicked
*/
public abstract void onDebouncedClick(View v);
/**
* The one and only constructor
*
* @param minimumIntervalMillis The minimum allowed time between clicks - any click sooner than this after a previous click will be rejected
*/
public DebouncedOnClickListener(long minimumIntervalMillis) {
this.minimumIntervalMillis = minimumIntervalMillis;
this.lastClickMap = new WeakHashMap<>();
}
@Override
public void onClick(View clickedView) {
Long previousClickTimestamp = lastClickMap.get(clickedView);
long currentTimestamp = SystemClock.uptimeMillis();
if (previousClickTimestamp == null || Math.abs(currentTimestamp - previousClickTimestamp) > minimumIntervalMillis) {
onDebouncedClick(clickedView);
lastClickMap.put(clickedView, currentTimestamp);
}
}
}
================================================
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/ImageLoader.java
================================================
/*******************************************************************************
* Copyright 2016 stfalcon.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.stfalcon.chatkit.commons;
import android.widget.ImageView;
import androidx.annotation.Nullable;
/**
* Callback for implementing images loading in message list
*/
public interface ImageLoader {
void loadImage(ImageView imageView, @Nullable String url, @Nullable Object payload);
}
================================================
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/InputTrackingRecyclerViewAdapter.java
================================================
package com.stfalcon.chatkit.commons;
import android.view.KeyEvent;
import android.view.View;
import androidx.recyclerview.widget.RecyclerView;
/**
* Created by vektor on 31/05/16.
*/
public abstract class InputTrackingRecyclerViewAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {
private int mSelectedItem = 0;
private RecyclerView mRecyclerView;
@Override
public void onAttachedToRecyclerView(final RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
mRecyclerView = recyclerView;
// Handle key up and key down and attempt to move selection
recyclerView.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
RecyclerView.LayoutManager lm = recyclerView.getLayoutManager();
// Return false if scrolled to the bounds and allow focus to move off the list
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (isConfirmButton(event)) {
if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) == KeyEvent.FLAG_LONG_PRESS) {
mRecyclerView.findViewHolderForAdapterPosition(mSelectedItem).itemView.performLongClick();
} else {
event.startTracking();
}
return true;
} else {
if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
return tryMoveSelection(lm, 1);
} else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
return tryMoveSelection(lm, -1);
}
}
} else if (event.getAction() == KeyEvent.ACTION_UP && isConfirmButton(event) && ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != KeyEvent.FLAG_LONG_PRESS)) {
mRecyclerView.findViewHolderForAdapterPosition(mSelectedItem).itemView.performClick();
return true;
}
return false;
}
});
}
private boolean tryMoveSelection(RecyclerView.LayoutManager lm, int direction) {
int nextSelectItem = mSelectedItem + direction;
// If still within valid bounds, move the selection, notify to redraw, and scroll
if (nextSelectItem >= 0 && nextSelectItem < getItemCount()) {
notifyItemChanged(mSelectedItem);
mSelectedItem = nextSelectItem;
notifyItemChanged(mSelectedItem);
//lm.scrollToPosition(mSelectedItem);
mRecyclerView.smoothScrollToPosition(mSelectedItem);
return true;
}
return false;
}
public int getSelectedItem() {
return mSelectedItem;
}
public void setSelectedItem(int selectedItem) {
mSelectedItem = selectedItem;
}
public RecyclerView getRecyclerView() {
return mRecyclerView;
}
@Override
public void onBindViewHolder(VH holder, int position) {
onBindViewHolder(holder, position);
}
public static boolean isConfirmButton(KeyEvent event) {
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_BUTTON_A:
return true;
default:
return false;
}
}
}
================================================
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/Style.java
================================================
/*******************************************************************************
* Copyright 2016 stfalcon.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.stfalcon.chatkit.commons;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Build.VERSION;
import android.util.AttributeSet;
import android.util.TypedValue;
import androidx.annotation.AttrRes;
import androidx.annotation.ColorRes;
import androidx.annotation.DimenRes;
import androidx.annotation.DrawableRes;
import androidx.core.content.ContextCompat;
import com.stfalcon.chatkit.R;
/**
* Base class for chat component styles
*/
public abstract class Style {
protected Context context;
protected Resources resources;
protected AttributeSet attrs;
protected Style(Context context, AttributeSet attrs) {
this.context = context;
this.resources = context.getResources();
this.attrs = attrs;
}
protected final int getSystemAccentColor() {
return getSystemColor(VERSION.SDK_INT >= 21 ? android.R.attr.colorAccent : R.attr.colorAccent);
}
protected final int getSystemPrimaryColor() {
return getSystemColor(VERSION.SDK_INT >= 21 ? android.R.attr.colorPrimary : R.attr.colorPrimary);
}
protected final int getSystemPrimaryDarkColor() {
return getSystemColor(VERSION.SDK_INT >= 21 ? android.R.attr.colorPrimaryDark : R.attr.colorPrimaryDark);
}
protected final int getSystemPrimaryTextColor() {
return getSystemColor(android.R.attr.textColorPrimary);
}
protected final int getSystemHintColor() {
return getSystemColor(android.R.attr.textColorHint);
}
protected final int getSystemColor(@AttrRes int attr) {
TypedValue typedValue = new TypedValue();
TypedArray a = context.obtainStyledAttributes(typedValue.data, new int[]{attr});
// MOD: Invisible link fix on old devices (provide the default color)
int color = a.getColor(0, getColor(R.color.dark_red));
a.recycle();
return color;
}
protected final int getDimension(@DimenRes int dimen) {
return resources.getDimensionPixelSize(dimen);
}
protected final int getColor(@ColorRes int color) {
return ContextCompat.getColor(context, color);
}
protected final Drawable getDrawable(@DrawableRes int drawable) {
return ContextCompat.getDrawable(context, drawable);
}
protected final Drawable getVectorDrawable(@DrawableRes int drawable) {
return ContextCompat.getDrawable(context, drawable);
}
}
================================================
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/ViewHolder.java
================================================
/*******************************************************************************
* Copyright 2016 stfalcon.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.stfalcon.chatkit.commons;
import android.view.View;
import androidx.recyclerview.widget.RecyclerView;
/**
* Base ViewHolder
*/
public abstract class ViewHolder<DATA> extends RecyclerView.ViewHolder {
public abstract void onBind(DATA data);
public ViewHolder(View itemView) {
super(itemView);
}
}
================================================
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/models/IDialog.java
================================================
/*******************************************************************************
* Copyright 2016 stfalcon.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.stfalcon.chatkit.commons.models;
import java.util.List;
/**
* For implementing by real dialog model
*/
public interface IDialog<MESSAGE extends IMessage> {
String getId();
String getDialogPhoto();
String getDialogName();
List<? extends IUser> getUsers();
MESSAGE getLastMessage();
void setLastMessage(MESSAGE message);
int getUnreadCount();
}
================================================
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/models/IMessage.java
================================================
/*******************************************************************************
* Copyright 2016 stfalcon.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.stfalcon.chatkit.commons.models;
import java.util.Date;
/**
* For implementing by real message model
*/
public interface IMessage {
/**
* Returns message identifier
*
* @return the message id
*/
String getId();
/**
* Returns message text
*
* @return the message text
*/
CharSequence getText();
/**
* Returns message author. See the {@link IUser} for more details
*
* @return the message author
*/
IUser getUser();
/**
* Returns message creation date
*
* @return the message creation date
*/
Date getCreatedAt();
static boolean checkMessage(IMessage message) {
return message != null && message.getId() != null && message.getUser() != null && message.getUser().getId() != null
&& message.getText() != null;
}
}
================================================
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/models/IUser.java
================================================
/*******************************************************************************
* Copyright 2016 stfalcon.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.stfalcon.chatkit.commons.models;
/**
* For implementing by real user model
*/
public interface IUser {
/**
* Returns the user's id
*
* @return the user's id
*/
String getId();
/**
* Returns the user's name
*
* @return the user's name
*/
String getName();
/**
* Returns the user's avatar image url
*
* @return the user's avatar image url
*/
String getAvatar();
}
================================================
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/models/MessageContentType.java
================================================
/*******************************************************************************
* Copyright 2016 stfalcon.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.stfalcon.chatkit.commons.models;
import androidx.annotation.Nullable;
import com.stfalcon.chatkit.messages.MessageHolders;
/*
* Created by troy379 on 28.03.17.
*/
/**
* Interface used to mark messages as custom content types. For its representation see {@link MessageHolders}
*/
public interface MessageContentType extends IMessage {
/**
* Default media type for image message.
*/
interface Image extends IMessage {
@Nullable
String getImageUrl();
}
// other default types will be here
}
================================================
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/widgets/FocusFixRelativeLayout.java
================================================
package com.stfalcon.chatkit.commons.widgets;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
/**
* https://stackoverflow.com/questions/34277425/recyclerview-items-lose-focus
*/
public class FocusFixRelativeLayout extends RelativeLayout {
public FocusFixRelativeLayout(Context context) {
super(context);
}
public FocusFixRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FocusFixRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@SuppressWarnings("NewApi")
public FocusFixRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public void clearFocus() {
if (getParent() != null) {
super.clearFocus();
}
}
}
================================================
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/widgets/WrapWidthTextView.java
================================================
package com.stfalcon.chatkit.commons.widgets;
import android.content.Context;
import android.text.Layout;
import android.util.AttributeSet;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;
/**
* Alter multiline TextView behavior to wrap content exactly.<br/>
* <a href="https://stackoverflow.com/questions/7439748/why-is-wrap-content-in-multiple-line-textview-filling-parent">Original discussion 1</a><br/>
* <a href="https://stackoverflow.com/questions/10913384/how-to-make-textview-wrap-its-multiline-content-exactly">Original discussion 2</a><br/>
*/
public class WrapWidthTextView extends AppCompatTextView {
public WrapWidthTextView(@NonNull Context context) {
super(context);
}
public WrapWidthTextView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public WrapWidthTextView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Layout layout = getLayout();
if (layout != null) {
int width = (int) Math.ceil(getMaxLineWidth(layout))
+ getCompoundPaddingLeft() + getCompoundPaddingRight();
int height = getMeasuredHeight();
setMeasuredDimension(width, height);
}
}
private float getMaxLineWidth(Layout layout) {
float max_width = 0.0f;
int lines = layout.getLineCount();
for (int i = 0; i < lines; i++) {
if (layout.getLineWidth(i) > max_width) {
max_width = layout.getLineWidth(i);
}
}
return max_width;
}
}
================================================
FILE: chatkit/src/main/java/com/stfalcon/chatkit/dialogs/DialogListStyle.java
================================================
/*******************************************************************************
* Copyright 2016 stfalcon.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.stfalcon.chatkit.dialogs;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.util.AttributeSet;
import com.stfalcon.chatkit.R;
import com.stfalcon.chatkit.commons.Style;
/**
* Style for DialogList customization by xml attributes
*/
@SuppressWarnings("WeakerAccess")
class DialogListStyle extends Style {
private int dialogTitleTextColor;
private int dialogTitleTextSize;
private int dialogTitleTextStyle;
private int dialogUnreadTitleTextColor;
private int dialogUnreadTitleTextStyle;
private int dialogMessageTextColor;
private int dialogMessageTextSize;
private int dialogMessageTextStyle;
private int dialogUnreadMessageTextColor;
private int dialogUnreadMessageTextStyle;
private int dialogDateColor;
private int dialogDateSize;
private int dialogDateStyle;
private int dialogUnreadDateColor;
private int dialogUnreadDateStyle;
private boolean dialogUnreadBubbleEnabled;
private int dialogUnreadBubbleTextColor;
private int dialogUnreadBubbleTextSize;
private int dialogUnreadBubbleTextStyle;
private int dialogUnreadBubbleBackgroundColor;
private int dialogAvatarWidth;
private int dialogAvatarHeight;
private boolean dialogMessageAvatarEnabled;
private int dialogMessageAvatarWidth;
private int dialogMessageAvatarHeight;
private boolean dialogDividerEnabled;
private int dialogDividerColor;
private int dialogDividerLeftPadding;
private int dialogDividerRightPadding;
private int dialogItemBackground;
private int dialogUnreadItemBackground;
static DialogListStyle parse(Context context, AttributeSet attrs) {
DialogListStyle style = new DialogListStyle(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DialogsList);
//Item background
style.dialogItemBackground = typedArray.getColor(R.styleable.DialogsList_dialogItemBackground,
style.getColor(R.color.transparent));
style.dialogUnreadItemBackground = typedArray.getColor(R.styleable.DialogsList_dialogUnreadItemBackground,
style.getColor(R.color.transparent));
//Title text
style.dialogTitleTextColor = typedArray.getColor(R.styleable.DialogsList_dialogTitleTextColor,
style.getColor(R.color.dialog_title_text));
style.dialogTitleTextSize = typedArray.getDimensionPixelSize(R.styleable.DialogsList_dialogTitleTextSize,
context.getResources().getDimensionPixelSize(R.dimen.dialog_title_text_size));
style.dialogTitleTextStyle = typedArray.getInt(R.styleable.DialogsList_dialogTitleTextStyle, Typeface.NORMAL);
//Title unread text
style.dialogUnreadTitleTextColor = typedArray.getColor(R.styleable.DialogsList_dialogUnreadTitleTextColor,
style.getColor(R.color.dialog_title_text));
style.dialogUnreadTitleTextStyle = typedArray.getInt(R.styleable.DialogsList_dialogUnreadTitleTextStyle, Typeface.NORMAL);
//Message text
style.dialogMessageTextColor = typedArray.getColor(R.styleable.DialogsList_dialogMessageTextColor,
style.getColor(R.color.dialog_message_text));
style.dialogMessageTextSize = typedArray.getDimensionPixelSize(R.styleable.DialogsList_dialogMessageTextSize,
context.getResources().getDimensionPixelSize(R.dimen.dialog_message_text_size));
style.dialogMessageTextStyle = typedArray.getInt(R.styleable.DialogsList_dialogMessageTextStyle, Typeface.NORMAL);
//Message unread text
style.dialogUnreadMessageTextColor = typedArray.getColor(R.styleable.DialogsList_dialogUnreadMessageTextColor,
style.getColor(R.color.dialog_message_text));
style.dialogUnreadMessageTextStyle = typedArray.getInt(R.styleable.DialogsList_dialogUnreadMessageTextStyle, Typeface.NORMAL);
//Date text
style.dialogDateColor = typedArray.getColor(R.styleable.DialogsList_dialogDateColor,
style.getColor(R.color.dialog_date_text));
style.dialogDateSize = typedArray.getDimensionPixelSize(R.styleable.DialogsList_dialogDateSize,
context.getResources().getDimensionPixelSize(R.dimen.dialog_date_text_size));
style.dialogDateStyle = typedArray.getInt(R.styleable.DialogsList_dialogDateStyle, Typeface.NORMAL);
//Date unread text
style.dialogUnreadDateColor = typedArray.getColor(R.styleable.DialogsList_dialogUnreadDateColor,
style.getColor(R.color.dialog_date_text));
style.dialogUnreadDateStyle = typedArray.getInt(R.styleable.DialogsList_dialogUnreadDateStyle, Typeface.NORMAL);
//Unread bubble
style.dialogUnreadBubbleEnabled = typedArray.getBoolean(R.styleable.DialogsList_dialogUnreadBubbleEnabled, true);
style.dialogUnreadBubbleBackgroundColor = typedArray.getColor(R.styleable.DialogsList_dialogUnreadBubbleBackgroundColor,
style.getColor(R.color.dialog_unread_bubble));
//Unread bubble text
style.dialogUnreadBubbleTextColor = typedArray.getColor(R.styleable.DialogsList_dialogUnreadBubbleTextColor,
style.getColor(R.color.dialog_unread_text));
style.dialogUnreadBubbleTextSize = typedArray.getDimensionPixelSize(R.styleable.DialogsList_dialogUnreadBubbleTextSize,
context.getResources().getDimensionPixelSize(R.dimen.dialog_unread_bubble_text_size));
style.dialogUnreadBubbleTextStyle = typedArray.getInt(R.styleable.DialogsList_dialogUnreadBubbleTextStyle, Typeface.NORMAL);
//Avatar
style.dialogAvatarWidth = typedArray.getDimensionPixelSize(R.styleable.DialogsList_dialogAvatarWidth,
context.getResources().getDimensionPixelSize(R.dimen.dialog_avatar_width));
style.dialogAvatarHeight = typedArray.getDimensionPixelSize(R.styleable.DialogsList_dialogAvatarHeight,
context.getResources().getDimensionPixelSize(R.dimen.dialog_avatar_height));
//Last message avatar
style.dialogMessageAvatarEnabled = typedArray.getBoolean(R.styleable.DialogsList_dialogMessageAvatarEnabled, true);
style.dialogMessageAvatarWidth = typedArray.getDimensionPixelSize(R.styleable.DialogsList_dialogMessageAvatarWidth,
context.getResources().getDimensionPixelSize(R.dimen.dialog_last_message_avatar_width));
style.dialogMessageAvatarHeight = typedArray.getDimensionPixelSize(R.styleable.DialogsList_dialogMessageAvatarHeight,
context.getResources().getDimensionPixelSize(R.dimen.dialog_last_message_avatar_height));
//Divider
style.dialogDividerEnabled = typedArray.getBoolean(R.styleable.DialogsList_dialogDividerEnabled, true);
style.dialogDividerColor = typedArray.getColor(R.styleable.DialogsList_dialogDividerColor, style.getColor(R.color.dialog_divider));
style.dialogDividerLeftPadding = typedArray.getDimensionPixelSize(R.styleable.DialogsList_dialogDividerLeftPadding,
context.getResources().getDimensionPixelSize(R.dimen.dialog_divider_margin_left));
style.dialogDividerRightPadding = typedArray.getDimensionPixelSize(R.styleable.DialogsList_dialogDividerRightPadding,
context.getResources().getDimensionPixelSize(R.dimen.dialog_divider_margin_right));
typedArray.recycle();
return style;
}
private DialogListStyle(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected int getDialogTitleTextColor() {
return dialogTitleTextColor;
}
protected int getDialogTitleTextSize() {
return dialogTitleTextSize;
}
protected int getDialogTitleTextStyle() {
return dialogTitleTextStyle;
}
protected int getDialogUnreadTitleTextColor() {
return dialogUnreadTitleTextColor;
}
protected int getDialogUnreadTitleTextStyle() {
return dialogUnreadTitleTextStyle;
}
protected int getDialogMessageTextColor() {
return dialogMessageTextColor;
}
protected int getDialogMessageTextSize() {
return dialogMessageTextSize;
}
protected int getDialogMessageTextStyle() {
return dialogMessageTextStyle;
}
protected int getDialogUnreadMessageTextColor() {
return dialogUnreadMessageTextColor;
}
protected int getDialogUnreadMessageTextStyle() {
return dialogUnreadMessageTextStyle;
}
protected int getDialogDateColor() {
return dialogDateColor;
}
protected int getDialogDateSize() {
return dialogDateSize;
}
protected int getDialogDateStyle() {
return dialogDateStyle;
}
protected int getDialogUnreadDateColor() {
return dialogUnreadDateColor;
}
protected int getDialogUnreadDateStyle() {
return dialogUnreadDateStyle;
}
protected boolean isDialogUnreadBubbleEnabled() {
return dialogUnreadBubbleEnabled;
}
protected int getDialogUnreadBubbleTextColor() {
return dialogUnreadBubbleTextColor;
}
protected int getDialogUnreadBubbleTextSize() {
return dialogUnreadBubbleTextSize;
}
protected int getDialogUnreadBubbleTextStyle() {
return dialogUnreadBubbleTextStyle;
}
protected int getDialogUnreadBubbleBackgroundColor() {
return dialogUnreadBubbleBackgroundColor;
}
protected int getDialogAvatarWidth() {
return dialogAvatarWidth;
}
protected int getDialogAvatarHeight() {
return dialogAvatarHeight;
}
protected boolean isDialogDividerEnabled() {
return dialogDividerEnabled;
}
protected int getDialogDividerColor() {
return dialogDividerColor;
}
protected int getDialogDividerLeftPadding() {
return dialogDividerLeftPadding;
}
protected int getDialogDividerRightPadding() {
return dialogDividerRightPadding;
}
protected int getDialogItemBackground() {
return dialogItemBackground;
}
protected int getDialogUnreadItemBackground() {
return dialogUnreadItemBackground;
}
protected boolean isDialogMessageAvatarEnabled() {
return dialogMessageAvatarEnabled;
}
protected int getDialogMessageAvatarWidth() {
return dialogMessageAvatarWidth;
}
protected int getDialogMessageAvatarHeight() {
return dialogMessageAvatarHeight;
}
}
================================================
FILE: chatkit/src/main/java/com/stfalcon/chatkit/dialogs/DialogsList.java
================================================
/*******************************************************************************
* Copyright 2016 stfalcon.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.stfalcon.chatkit.dialogs;
import android.content.Context;
import android.util.AttributeSet;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SimpleItemAnimator;
import com.stfalcon.chatkit.commons.models.IDialog;
/**
* Component for displaying list of dialogs
*/
public class DialogsList extends RecyclerView {
private DialogListStyle dialogStyle;
public DialogsList(Context context) {
super(context);
}
public DialogsList(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
parseStyle(context, attrs);
}
public DialogsList(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
parseStyle(context, attrs);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
LinearLayoutManager layout = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
SimpleItemAnimator animator = new DefaultItemAnimator();
setLayoutManager(layout);
setItemAnimator(animator);
}
/**
* Don't use this method for setting your adapter, otherwise exception will by thrown.
* Call {@link #setAdapter(DialogsListAdapter)} instead.
*/
@Override
public void setAdapter(Adapter adapter) {
throw new IllegalArgumentException("You can't set adapter to DialogsList. Use #setAdapter(DialogsListAdapter) instead.");
}
/**
* Sets adapter for DialogsList
*
* @param adapter Adapter. Must extend DialogsListAdapter
* @param <DIALOG> Dialog model class
*/
public <DIALOG extends IDialog<?>>
void setAdapter(DialogsListAdapter<DIALOG> adapter) {
setAdapter(adapter, false);
}
/**
* Sets adapter for DialogsList
*
* @param adapter Adapter. Must extend DialogsListAdapter
* @param reverseLayout weather to use reverse layout for layout manager.
* @param <DIALOG> Dialog model class
*/
public <DIALOG extends IDialog<?>>
void setAdapter(DialogsListAdapter<DIALOG> adapter, boolean reverseLayout) {
SimpleItemAnimator itemAnimator = new DefaultItemAnimator();
itemAnimator.setSupportsChangeAnimations(false);
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext(),
LinearLayoutManager.VERTICAL, reverseLayout);
setItemAnimator(itemAnimator);
setLayoutManager(layoutManager);
adapter.setStyle(dialogStyle);
super.setAdapter(adapter);
}
@SuppressWarnings("ResourceType")
private void parseStyle(Context context, AttributeSet attrs) {
dialogStyle = DialogListStyle.parse(context, attrs);
}
}
================================================
FILE: chatkit/src/main/java/com/stfalcon/chatkit/dialogs/DialogsListAdapter.java
================================================
/******************************************************************************
* Copyright 2016 stfalcon.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.stfalcon.chatkit.dialogs;
import android.graphics.Typeface;
import android.graphics.drawable.GradientDrawable;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.LayoutRes;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import com.stfalcon.chatkit.R;
import com.stfalcon.chatkit.commons.ImageLoader;
import com.stfalcon.chatkit.commons.ViewHolder;
import com.stfalcon.chatkit.commons.models.IDialog;
import com.stfalcon.chatkit.commons.models.IMessage;
import com.stfalcon.chatkit.utils.DateFormatter;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
/**
* Adapter for {@link DialogsList}
*/
@SuppressWarnings("WeakerAccess")
public class DialogsListAdapter<DIALOG extends IDialog>
extends RecyclerView.Adapter<DialogsListAdapter.BaseDialogViewHolder> {
protected List<DIALOG> items = new ArrayList<>();
private int itemLayoutId;
private Class<? extends BaseDialogViewHolder> holderClass;
private ImageLoader imageLoader;
private OnDialogClickListener<DIALOG> onDialogClickListener;
private OnDialogViewClickListener<DIALOG> onDialogViewClickListener;
private OnDialogLongClickListener<DIALOG> onLongItemClickListener;
private OnDialogViewLongClickListener<DIALOG> onDialogViewLongClickListener;
private DialogListStyle dialogStyle;
private DateFormatter.Formatter datesFormatter;
/**
* For default list item layout and view holder
*
* @param imageLoader image loading method
*/
public DialogsListAdapter(ImageLoader imageLoader) {
this(R.layout.item_dialog, DialogViewHolder.class, imageLoader);
}
/**
* For custom list item layout and default view holder
*
* @param itemLayoutId custom list item resource id
* @param imageLoader image loading method
*/
public DialogsListAdapter(@LayoutRes int itemLayoutId, ImageLoader imageLoader) {
this(itemLayoutId, DialogViewHolder.class, imageLoader);
}
/**
* For custom list item layout and custom view holder
*
* @param itemLayoutId custom list item resource id
* @param holderClass custom view holder class
* @param imageLoader image loading method
*/
public DialogsListAdapter(@LayoutRes int itemLayoutId, Class<? extends BaseDialogViewHolder> holderClass,
ImageLoader imageLoader) {
this.itemLayoutId = itemLayoutId;
this.holderClass = holderClass;
this.imageLoader = imageLoader;
}
@SuppressWarnings("unchecked")
@Override
public void onBindViewHolder(BaseDialogViewHolder holder, int position) {
holder.setImageLoader(imageLoader);
holder.setOnDialogClickListener(onDialogClickListener);
holder.setOnDialogViewClickListener(onDialogViewClickListener);
holder.setOnLongItemClickListener(onLongItemClickListener);
holder.setOnDialogViewLongClickListener(onDialogViewLongClickListener);
holder.setDatesFormatter(datesFormatter);
holder.onBind(items.get(position));
}
@Override
public BaseDialogViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(itemLayoutId, parent, false);
//create view holder by reflation
try {
Constructor<? extends BaseDialogViewHolder> constructor = holderClass.getDeclaredConstructor(View.class);
constructor.setAccessible(true);
BaseDialogViewHolder baseDialogViewHolder = constructor.newInstance(v);
if (baseDialogViewHolder instanceof DialogViewHolder) {
((DialogViewHolder) baseDialogViewHolder).setDialogStyle(dialogStyle);
}
return baseDialogViewHolder;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* @return size of dialogs list
*/
@Override
public int getItemCount() {
return items.size();
}
/**
* remove item with id
*
* @param id dialog i
*/
public void deleteById(String id) {
for (int i = 0; i < items.size(); i++) {
if (items.get(i).getId().equals(id)) {
items.remove(i);
notifyItemRemoved(i);
}
}
}
/**
* Returns {@code true} if, and only if, dialogs count in adapter is non-zero.
*
* @return {@code true} if size is 0, otherwise {@code false}
*/
public boolean isEmpty() {
return items.isEmpty();
}
/**
* clear dialogs list
*/
public void clear() {
if (items != null) {
items.clear();
}
notifyDataSetChanged();
}
/**
* Set dialogs list
*
* @param items dialogs list
*/
public void setItems(List<DIALOG> items) {
this.items = items;
notifyDataSetChanged();
}
/**
* Add dialogs items
*
* @param newItems new dialogs list
*/
public void addItems(List<DIALOG> newItems) {
if (newItems != null) {
if (items == null) {
items = new ArrayList<>();
}
int curSize = items.size();
items.addAll(newItems);
notifyItemRangeInserted(curSize, items.size());
}
}
/**
* Add dialog to the end of dialogs list
*
* @param dialog dialog item
*/
public void addItem(DIALOG dialog) {
items.add(dialog);
notifyItemInserted(items.size() - 1);
}
/**
* Add dialog to dialogs list
*
* @param dialog dialog item
* @param position position in dialogs list
*/
public void addItem(int position, DIALOG dialog) {
items.add(position, dialog);
notifyItemInserted(position);
}
/**
* Move an item
*
* @param fromPosition the actual position of the item
* @param toPosition the new position of the item
*/
public void moveItem(int fromPosition, int toPosition) {
DIALOG dialog = items.remove(fromPosition);
items.add(toPosition, dialog);
notifyItemMoved(fromPosition, toPosition);
}
/**
* Update dialog by position in dialogs list
*
* @param position position in dialogs list
* @param item new dialog item
*/
public void updateItem(int position, DIALOG item) {
if (items == null) {
items = new ArrayList<>();
}
items.set(position, item);
notifyItemChanged(position);
}
/**
* Update dialog by dialog id
*
* @param item new dialog item
*/
public void updateItemById(DIALOG item) {
if (items == null) {
items = new ArrayList<>();
}
for (int i = 0; i < items.size(); i++) {
if (items.get(i).getId().equals(item.getId())) {
items.set(i, item);
notifyItemChanged(i);
break;
}
}
}
/**
* Upsert dialog in dialogs list or add it to then end of dialogs list
*
* @param item dialog item
*/
public void upsertItem(DIALOG item) {
boolean updated = false;
for (int i = 0; i < items.size(); i++) {
if (items.get(i).getId().equals(item.getId())) {
items.set(i, item);
notifyItemChanged(i);
updated = true;
break;
}
}
if (!updated) {
addItem(item);
}
}
/**
* Find an item by its id
*
* @param id the wanted item's id
* @return the found item, or null
*/
@Nullable
public DIALOG getItemById(String id) {
if (items == null) {
items = new ArrayList<>();
}
for (DIALOG item : items) {
if (item.getId() == null && id == null) {
return item;
} else if (item.getId() != null && item.getId().equals(id)) {
return item;
}
}
return null;
}
/**
* Update last message in dialog and swap item to top of list.
*
* @param dialogId Dialog ID
* @param message New message
* @return false if dialog doesn't exist.
*/
@SuppressWarnings("unchecked")
public boolean updateDialogWithMessage(String dialogId, IMessage message) {
boolean dialogExist = false;
for (int i = 0; i < items.size(); i++) {
if (items.get(i).getId().equals(dialogId)) {
items.get(i).setLastMessage(message);
notifyItemChanged(i);
if (i != 0) {
Collections.swap(items, i, 0);
notifyItemMoved(i, 0);
}
dialogExist = true;
break;
}
}
return dialogExist;
}
/**
* Sort dialog by last message date
*/
public void sortByLastMessageDate() {
Collections.sort(items, (o1, o2) -> {
if (o1.getLastMessage().getCreatedAt().after(o2.getLastMessage().getCreatedAt())) {
return -1;
} else if (o1.getLastMessage().getCreatedAt().before(o2.getLastMessage().getCreatedAt())) {
return 1;
} else return 0;
});
notifyDataSetChanged();
}
/**
* Sort items with rules of comparator
*
* @param comparator Comparator
*/
public void sort(Comparator<DIALOG> comparator) {
Collections.sort(items, comparator);
notifyDataSetChanged();
}
/**
* @return registered image loader
*/
public ImageLoader getImageLoader() {
return imageLoader;
}
/**
* Register a callback to be invoked when image need to load.
*
* @param imageLoader image loading method
*/
public void setImageLoader(ImageLoader imageLoader) {
this.imageLoader = imageLoader;
}
/**
* @return the item click callback.
*/
public OnDialogClickListener getOnDialogClickListener() {
return onDialogClickListener;
}
/**
* Register a callback to be invoked when item is clicked.
*
* @param onDialogClickListener on click item callback
*/
public void setOnDialogClickListener(OnDialogClickListener<DIALOG> onDialogClickListener) {
this.onDialogClickListener = onDialogClickListener;
}
/**
* @return the view click callback.
*/
public OnDialogViewClickListener getOnDialogViewClickListener() {
return onDialogViewClickListener;
}
/**
* Register a callback to be invoked when dialog view is clicked.
*
* @param clickListener on click item callback
*/
public void setOnDialogViewClickListener(OnDialogViewClickListener<DIALOG> clickListener) {
this.onDialogViewClickListener = clickListener;
}
/**
* @return on long click item callback
*/
public OnDialogLongClickListener getOnLongItemClickListener() {
return onLongItemClickListener;
}
/**
* Register a callback to be invoked when item is long clicked.
*
* @param onLongItemClickListener on long click item callback
*/
public void setOnDialogLongClickListener(OnDialogLongClickListener<DIALOG> onLongItemClickListener) {
this.onLongItemClickListener = onLongItemClickListener;
}
/**
* @return on view long click callback
*/
public OnDialogViewLongClickListener<DIALOG> getOnDialogViewLongClickListener() {
return onDialogViewLongClickListener;
}
/**
* Register a callback to be invoked when item view is long clicked.
*
* @param clickListener on long click item callback
*/
public void setOnDialogViewLongClickListener(OnDialogViewLongClickListener<DIALOG> clickListener) {
this.onDialogViewLongClickListener = clickListener;
}
/**
* Sets custom {@link DateFormatter.Formatter} for text representation of last message date.
*/
public void setDatesFormatter(DateFormatter.Formatter datesFormatter) {
this.datesFormatter = datesFormatter;
}
//TODO ability to set style programmatically
void setStyle(DialogListStyle dialogStyle) {
this.dialogStyle = dialogStyle;
}
/**
* @return the position of a dialog in the dialogs list.
*/
public int getDialogPosition(DIALOG dialog) {
return this.items.indexOf(dialog);
}
/*
* LISTENERS
* */
public interface OnDialogClickListener<DIALOG extends IDialog> {
void onDialogClick(DIALOG dialog);
}
public interface OnDialogViewClickListener<DIALOG extends IDialog> {
void onDialogViewClick(View view, DIALOG dialog);
}
public interface OnDialogLongClickListener<DIALOG extends IDialog> {
void onDialogLongClick(DIALOG dialog);
}
public interface OnDialogViewLongClickListener<DIALOG extends IDialog> {
void onDialogViewLongClick(View view, DIALOG dialog);
}
/*
* HOLDERS
* */
public abstract static class BaseDialogViewHolder<DIALOG extends IDialog>
extends ViewHolder<DIALOG> {
protected ImageLoader imageLoader;
protected OnDialogClickListener<DIALOG> onDialogClickListener;
protected OnDialogLongClickListener<DIALOG> onLongItemClickListener;
protected OnDialogViewClickListener<DIALOG> onDialogViewClickListener;
protected OnDialogViewLongClickListener<DIALOG> onDialogViewLongClickListener;
protected DateFormatter.Formatter datesFormatter;
public BaseDialogViewHolder(View itemView) {
super(itemView);
}
void setImageLoader(ImageLoader imageLoader) {
this.imageLoader = imageLoader;
}
protected void setOnDialogClickListener(OnDialogClickListener<DIALOG> onDialogClickListener) {
this.onDialogClickListener = onDialogClickListener;
}
protected void setOnDialogViewClickListener(OnDialogViewClickListener<DIALOG> onDialogViewClickListener) {
this.onDialogViewClickListener = onDialogViewClickListener;
}
protected void setOnLongItemClickListener(OnDialogLongClickListener<DIALOG> onLongItemClickListener) {
this.onLongItemClickListener = onLongItemClickListener;
}
protected void setOnDialogViewLongClickListener(OnDialogViewLongClickListener<DIALOG> onDialogViewLongClickListener) {
this.onDialogViewLongClickListener = onDialogViewLongClickListener;
}
public void setDatesFormatter(DateFormatter.Formatter dateHeadersFormatter) {
this.datesFormatter = dateHeadersFormatter;
}
}
public static class DialogViewHolder<DIALOG extends IDialog> extends BaseDialogViewHolder<DIALOG> {
protected DialogListStyle dialogStyle;
protected ViewGroup container;
protected ViewGroup root;
protected TextView tvName;
protected TextView tvDate;
protected ImageView ivAvatar;
protected ImageView ivLastMessageUser;
protected TextView tvLastMessage;
protected TextView tvBubble;
protected ViewGroup dividerContainer;
protected View divider;
public DialogViewHolder(View itemView) {
super(itemView);
root = itemView.findViewById(R.id.dialogRootLayout);
container = itemView.findViewById(R.id.dialogContainer);
tvName = itemView.findViewById(R.id.dialogName);
tvDate = itemView.findViewById(R.id.dialogDate);
tvLastMessage = itemView.findViewById(R.id.dialogLastMessage);
tvBubble = itemView.findViewById(R.id.dialogUnreadBubble);
ivLastMessageUser = itemView.findViewById(R.id.dialogLastMessageUserAvatar);
ivAvatar = itemView.findViewById(R.id.dialogAvatar);
dividerContainer = itemView.findViewById(R.id.dialogDividerContainer);
divider = itemView.findViewById(R.id.dialogDivider);
}
private void applyStyle() {
if (dialogStyle != null) {
//Texts
if (tvName != null) {
tvName.setTextSize(TypedValue.COMPLEX_UNIT_PX, dialogStyle.getDialogTitleTextSize());
}
if (tvLastMessage != null) {
tvLastMessage.setTextSize(TypedValue.COMPLEX_UNIT_PX, dialogStyle.getDialogMessageTextSize());
}
if (tvDate != null) {
tvDate.setTextSize(TypedValue.COMPLEX_UNIT_PX, dialogStyle.getDialogDateSize());
}
//Divider
if (divider != null)
divider.setBackgroundColor(dialogStyle.getDialogDividerColor());
if (dividerContainer != null)
dividerContainer.setPadding(dialogStyle.getDialogDividerLeftPadding(), 0,
dialogStyle.getDialogDividerRightPadding(), 0);
//Avatar
if (ivAvatar != null) {
ivAvatar.getLayoutParams().width = dialogStyle.getDialogAvatarWidth();
ivAvatar.getLayoutParams().height = dialogStyle.getDialogAvatarHeight();
}
//Last message user avatar
if (ivLastMessageUser != null) {
ivLastMessageUser.getLayoutParams().width = dialogStyle.getDialogMessageAvatarWidth();
ivLastMessageUser.getLayoutParams().height = dialogStyle.getDialogMessageAvatarHeight();
}
//Unread bubble
if (tvBubble != null) {
GradientDrawable bgShape = (GradientDrawable) tvBubble.getBackground();
bgShape.setColor(dialogStyle.getDialogUnreadBubbleBackgroundColor());
tvBubble.setVisibility(dialogStyle.isDialogDividerEnabled() ? VISIBLE : GONE);
tvBubble.setTextSize(TypedValue.COMPLEX_UNIT_PX, dialogStyle.getDialogUnreadBubbleTextSize());
tvBubble.setTextColor(dialogStyle.getDialogUnreadBubbleTextColor());
tvBubble.setTypeface(tvBubble.getTypeface(), dialogStyle.getDialogUnreadBubbleTextStyle());
}
}
}
private void applyDefaultStyle() {
if (dialogStyle != null) {
if (root != null) {
root.setBackgroundColor(dialogStyle.getDialogItemBackground());
}
if (tvName != null) {
tvName.setTextColor(dialogStyle.getDialogTitleTextColor());
tvName.setTypeface(Typeface.DEFAULT, dialogStyle.getDialogTitleTextStyle());
}
if (tvDate != null) {
tvDate.setTextColor(dialogStyle.getDialogDateColor());
tvDate.setTypeface(Typeface.DEFAULT, dialogStyle.getDialogDateStyle());
}
if (tvLastMessage != null) {
tvLastMessage.setTextColor(dialogStyle.getDialogMessageTextColor());
tvLastMessage.setTypeface(Typeface.DEFAULT, dialogStyle.getDialogMessageTextStyle());
}
}
}
private void applyUnreadStyle() {
if (dialogStyle != null) {
if (root != null) {
root.setBackgroundColor(dialogStyle.getDialogUnreadItemBackground());
}
if (tvName != null) {
tvName.setTextColor(dialogStyle.getDialogUnreadTitleTextColor());
tvName.setTypeface(Typeface.DEFAULT, dialogStyle.getDialogUnreadTitleTextStyle());
}
if (tvDate != null) {
tvDate.setTextColor(dialogStyle.getDialogUnreadDateColor());
tvDate.setTypeface(Typeface.DEFAULT, dialogStyle.getDialogUnreadDateStyle());
}
if (tvLastMessage != null) {
tvLastMessage.setTextColor(dialogStyle.getDialogUnreadMessageTextColor());
tvLastMessage.setTypeface(Typeface.DEFAULT, dialogStyle.getDialogUnreadMessageTextStyle());
}
}
}
@Override
public void onBind(final DIALOG dialog) {
if (dialog.getUnreadCount() > 0) {
applyUnreadStyle();
} else {
applyDefaultStyle();
}
//Set Name
tvName.setText(dialog.getDialogName());
//Set Date
String formattedDate = null;
if (dialog.getLastMessage() != null) {
Date lastMessageDate = dialog.getLastMessage().getCreatedAt();
if (datesFormatter != null) formattedDate = datesFormatter.format(lastMessageDate);
tvDate.setText(formattedDate == null
? getDateString(lastMessageDate)
: formattedDate);
} else {
tvDate.setText(null);
}
//Set Dialog avatar
if (imageLoader != null) {
imageLoader.loadImage(ivAvatar, dialog.getDialogPhoto(), null);
}
//Set Last message user avatar with check if there is last message
if (imageLoader != null && dialog.getLastMessage() != null) {
imageLoader.loadImage(ivLastMessageUser, dialog.getLastMessage().getUser().getAvatar(), null);
}
ivLastMessageUser.setVisibility(dialogStyle.isDialogMessageAvatarEnabled()
&& dialog.getUsers().size() > 1
&& dialog.getLastMessage() != null ? VISIBLE : GONE);
//Set Last message text
if (dialog.getLastMessage() != null) {
tvLastMessage.setText(dialog.getLastMessage().getText());
} else {
tvLastMessage.setText(null);
}
//Set Unread message count bubble
tvBubble.setText(String.valueOf(dialog.getUnreadCount()));
tvBubble.setVisibility(dialogStyle.isDialogUnreadBubbleEnabled() &&
dialog.getUnreadCount() > 0 ? VISIBLE : GONE);
container.setOnClickListener(view -> {
if (onDialogClickListener != null) {
onDialogClickListener.onDialogClick(dialog);
}
if (onDialogViewClickListener != null) {
onDialogViewClickListener.onDialogViewClick(view, dialog);
}
});
container.setOnLongClickListener(view -> {
if (onLongItemClickListener != null) {
onLongItemClickListener.onDialogLongClick(dialog);
}
if (onDialogViewLongClickListener != null) {
onDialogViewLongClickListener.onDialogViewLongClick(view, dialog);
}
return onLongItemClickListener != null || onDialogViewLongClickListener != null;
});
}
protected String getDateString(Date date) {
return DateFormatter.format(date, DateFormatter.Template.TIME);
}
protected DialogListStyle getDialogStyle() {
return dialogStyle;
}
protected void setDialogStyle(DialogListStyle dialogStyle) {
this.dialogStyle = dialogStyle;
applyStyle();
}
}
}
================================================
FILE: chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageHolders.java
================================================
package com.stfalcon.chatkit.messages;
import android.annotation.SuppressLint;
import android.text.Spannable;
import android.text.method.LinkMovementMethod;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.core.view.ViewCompat;
import com.stfalcon.chatkit.R;
import com.stfalcon.chatkit.commons.ImageLoader;
import com.stfalcon.chatkit.commons.ViewHolder;
import com.stfalcon.chatkit.commons.models.IMessage;
import com.stfalcon.chatkit.commons.models.MessageContentType;
import com.stfalcon.chatkit.utils.DateFormatter;
import com.stfalcon.chatkit.utils.RoundedImageView;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/*
* Created by troy379 on 31.03.17.
*/
@SuppressWarnings("WeakerAccess")
public class MessageHolders {
private static final short VIEW_TYPE_DATE_HEADER = 130;
private static final short VIEW_TYPE_STRING_HEADER = 133;
private static final short VIEW_TYPE_TEXT_MESSAGE = 131;
private static final short VIEW_TYPE_IMAGE_MESSAGE = 132;
private Class<? extends ViewHolder<Date>> dateHeaderHolder;
private Class<? extends ViewHolder<String>> stringHeaderHolder;
private int dateHeaderLayout;
private HolderConfig<IMessage> incomingTextConfig;
private HolderConfig<IMessage> outcomingTextConfig;
private HolderConfig<MessageContentType.Image> incomingImageConfig;
private HolderConfig<MessageContentType.Image> outcomingImageConfig;
private List<ContentTypeConfig> customContentTypes = new ArrayList<>();
private ContentChecker contentChecker;
public MessageHolders() {
this.dateHeaderHolder = DefaultDateHeaderViewHolder.class;
this.dateHeaderLayout = R.layout.item_date_header;
this.stringHeaderHolder = DefaultStringHeaderViewHolder.class;
this.incomingTextConfig = new HolderConfig<>(DefaultIncomingTextMessageViewHolder.class, R.layout.item_incoming_text_message);
this.outcomingTextConfig = new HolderConfig<>(DefaultOutcomingTextMessageViewHolder.class, R.layout.item_outcoming_text_message);
this.incomingImageConfig = new HolderConfig<>(DefaultIncomingImageMessageViewHolder.class, R.layout.item_incoming_image_message);
this.outcomingImageConfig = new HolderConfig<>(DefaultOutcomingImageMessageViewHolder.class, R.layout.item_outcoming_image_message);
}
/**
* Sets both of custom view holder class and layout resource for incoming text message.
*
* @param holder holder class.
* @param layout layout resource.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setIncomingTextConfig(
@NonNull Class<? extends BaseMessageViewHolder<? extends IMessage>> holder,
@LayoutRes int layout) {
this.incomingTextConfig.holder = holder;
this.incomingTextConfig.layout = layout;
return this;
}
/**
* Sets both of custom view holder class and layout resource for incoming text message.
*
* @param holder holder class.
* @param layout layout resource.
* @param payload custom data.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setIncomingTextConfig(
@NonNull Class<? extends BaseMessageViewHolder<? extends IMessage>> holder,
@LayoutRes int layout,
Object payload) {
this.incomingTextConfig.holder = holder;
this.incomingTextConfig.layout = layout;
this.incomingTextConfig.payload = payload;
return this;
}
/**
* Sets custom view holder class for incoming text message.
*
* @param holder holder class.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setIncomingTextHolder(
@NonNull Class<? extends BaseMessageViewHolder<? extends IMessage>> holder) {
this.incomingTextConfig.holder = holder;
return this;
}
/**
* Sets custom view holder class for incoming text message.
*
* @param holder holder class.
* @param payload custom data.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setIncomingTextHolder(
@NonNull Class<? extends BaseMessageViewHolder<? extends IMessage>> holder,
Object payload) {
this.incomingTextConfig.holder = holder;
this.incomingTextConfig.payload = payload;
return this;
}
/**
* Sets custom layout resource for incoming text message.
*
* @param layout layout resource.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setIncomingTextLayout(@LayoutRes int layout) {
this.incomingTextConfig.layout = layout;
return this;
}
/**
* Sets custom layout resource for incoming text message.
*
* @param layout layout resource.
* @param payload custom data.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setIncomingTextLayout(@LayoutRes int layout, Object payload) {
this.incomingTextConfig.layout = layout;
this.incomingTextConfig.payload = payload;
return this;
}
/**
* Sets both of custom view holder class and layout resource for outcoming text message.
*
* @param holder holder class.
* @param layout layout resource.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setOutcomingTextConfig(
@NonNull Class<? extends BaseMessageViewHolder<? extends IMessage>> holder,
@LayoutRes int layout) {
this.outcomingTextConfig.holder = holder;
this.outcomingTextConfig.layout = layout;
return this;
}
/**
* Sets both of custom view holder class and layout resource for outcoming text message.
*
* @param holder holder class.
* @param layout layout resource.
* @param payload custom data.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setOutcomingTextConfig(
@NonNull Class<? extends BaseMessageViewHolder<? extends IMessage>> holder,
@LayoutRes int layout,
Object payload) {
this.outcomingTextConfig.holder = holder;
this.outcomingTextConfig.layout = layout;
this.outcomingTextConfig.payload = payload;
return this;
}
/**
* Sets custom view holder class for outcoming text message.
*
* @param holder holder class.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setOutcomingTextHolder(
@NonNull Class<? extends BaseMessageViewHolder<? extends IMessage>> holder) {
this.outcomingTextConfig.holder = holder;
return this;
}
/**
* Sets custom view holder class for outcoming text message.
*
* @param holder holder class.
* @param payload custom data.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setOutcomingTextHolder(
@NonNull Class<? extends BaseMessageViewHolder<? extends IMessage>> holder,
Object payload) {
this.outcomingTextConfig.holder = holder;
this.outcomingTextConfig.payload = payload;
return this;
}
/**
* Sets custom layout resource for outcoming text message.
*
* @param layout layout resource.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setOutcomingTextLayout(@LayoutRes int layout) {
this.outcomingTextConfig.layout = layout;
return this;
}
/**
* Sets custom layout resource for outcoming text message.
*
* @param layout layout resource.
* @param payload custom data.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setOutcomingTextLayout(@LayoutRes int layout, Object payload) {
this.outcomingTextConfig.layout = layout;
this.outcomingTextConfig.payload = payload;
return this;
}
/**
* Sets both of custom view holder class and layout resource for incoming image message.
*
* @param holder holder class.
* @param layout layout resource.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setIncomingImageConfig(
@NonNull Class<? extends BaseMessageViewHolder<? extends MessageContentType.Image>> holder,
@LayoutRes int layout) {
this.incomingImageConfig.holder = holder;
this.incomingImageConfig.layout = layout;
return this;
}
/**
* Sets both of custom view holder class and layout resource for incoming image message.
*
* @param holder holder class.
* @param layout layout resource.
* @param payload custom data.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setIncomingImageConfig(
@NonNull Class<? extends BaseMessageViewHolder<? extends MessageContentType.Image>> holder,
@LayoutRes int layout,
Object payload) {
this.incomingImageConfig.holder = holder;
this.incomingImageConfig.layout = layout;
this.incomingImageConfig.payload = payload;
return this;
}
/**
* Sets custom view holder class for incoming image message.
*
* @param holder holder class.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setIncomingImageHolder(
@NonNull Class<? extends BaseMessageViewHolder<? extends MessageContentType.Image>> holder) {
this.incomingImageConfig.holder = holder;
return this;
}
/**
* Sets custom view holder class for incoming image message.
*
* @param holder holder class.
* @param payload custom data.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setIncomingImageHolder(
@NonNull Class<? extends BaseMessageViewHolder<? extends MessageContentType.Image>> holder,
Object payload) {
this.incomingImageConfig.holder = holder;
this.incomingImageConfig.payload = payload;
return this;
}
/**
* Sets custom layout resource for incoming image message.
*
* @param layout layout resource.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setIncomingImageLayout(@LayoutRes int layout) {
this.incomingImageConfig.layout = layout;
return this;
}
/**
* Sets custom layout resource for incoming image message.
*
* @param layout layout resource.
* @param payload custom data.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setIncomingImageLayout(@LayoutRes int layout, Object payload) {
this.incomingImageConfig.layout = layout;
this.incomingImageConfig.payload = payload;
return this;
}
/**
* Sets both of custom view holder class and layout resource for outcoming image message.
*
* @param holder holder class.
* @param layout layout resource.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setOutcomingImageConfig(
@NonNull Class<? extends BaseMessageViewHolder<? extends MessageContentType.Image>> holder,
@LayoutRes int layout) {
this.outcomingImageConfig.holder = holder;
this.outcomingImageConfig.layout = layout;
return this;
}
/**
* Sets both of custom view holder class and layout resource for outcoming image message.
*
* @param holder holder class.
* @param layout layout resource.
* @param payload custom data.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setOutcomingImageConfig(
@NonNull Class<? extends BaseMessageViewHolder<? extends MessageContentType.Image>> holder,
@LayoutRes int layout,
Object payload) {
this.outcomingImageConfig.holder = holder;
this.outcomingImageConfig.layout = layout;
this.outcomingImageConfig.payload = payload;
return this;
}
/**
* Sets custom view holder class for outcoming image message.
*
* @param holder holder class.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setOutcomingImageHolder(
@NonNull Class<? extends BaseMessageViewHolder<? extends MessageContentType.Image>> holder) {
this.outcomingImageConfig.holder = holder;
return this;
}
/**
* Sets custom view holder class for outcoming image message.
*
* @param holder holder class.
* @param payload custom data.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setOutcomingImageHolder(
@NonNull Class<? extends BaseMessageViewHolder<? extends MessageContentType.Image>> holder,
Object payload) {
this.outcomingImageConfig.holder = holder;
this.outcomingImageConfig.payload = payload;
return this;
}
/**
* Sets custom layout resource for outcoming image message.
*
* @param layout layout resource.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setOutcomingImageLayout(@LayoutRes int layout) {
this.outcomingImageConfig.layout = layout;
return this;
}
/**
* Sets custom layout resource for outcoming image message.
*
* @param layout layout resource.
* @param payload custom data.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setOutcomingImageLayout(@LayoutRes int layout, Object payload) {
this.outcomingImageConfig.layout = layout;
this.outcomingImageConfig.payload = payload;
return this;
}
/**
* Sets both of custom view holder class and layout resource for date header.
*
* @param holder holder class.
* @param layout layout resource.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setDateHeaderConfig(
@NonNull Class<? extends ViewHolder<Date>> holder,
@LayoutRes int layout) {
this.dateHeaderHolder = holder;
this.dateHeaderLayout = layout;
return this;
}
/**
* Sets custom view holder class for date header.
*
* @param holder holder class.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setDateHeaderHolder(@NonNull Class<? extends ViewHolder<Date>> holder) {
this.dateHeaderHolder = holder;
return this;
}
/**
* Sets custom layout reource for date header.
*
* @param layout layout resource.
* @return {@link MessageHolders} for subsequent configuration.
*/
public MessageHolders setDateHeaderLayout(@LayoutRes int layout) {
this.dateHeaderLayout = layout;
return this;
}
/**
* Registers custom content type (e.g. multimedia, events etc.)
*
* @param type unique id for content type
* @param holder holder class for incoming and outcoming messages
* @param incomingLayout layout resource for incoming message
* @param outcomingLayout layout resource for outcoming message
* @param contentChecker {@link ContentChecker} for registered type
* @return {@link MessageHolders} for subsequent configuration.
*/
public <TYPE extends MessageContentType>
MessageHolders registerContentType(
byte type, @NonNull Class<? extends BaseMessageViewHolder<TYPE>> holder,
@LayoutRes int incomingLayout,
@LayoutRes int outcomingLayout,
@NonNull ContentChecker contentChecker) {
return registerContentType(type,
holder, incomingLayout,
holder, outcomingLayout,
contentChecker);
}
/**
* Registers custom content type (e.g. multimedia, events etc.)
*
* @param type unique id for content type
* @param incomingHolder holder class for incoming message
* @param outcomingHolder holder class for outcoming message
* @param incomingLayout layout resource for incoming message
* @param outcomingLayout layout resource for outcoming message
* @param contentChecker {@link ContentChecker} for registered type
* @return {@link MessageHolders} for subsequent configuration.
*/
public <TYPE extends MessageContentType>
MessageHolders registerContentType(
byte type,
@NonNull Class<? extends BaseMessageViewHolder<TYPE>> incomingHolder, @LayoutRes int incomingLayout,
@NonNull Class<? extends BaseMessageViewHolder<TYPE>> outcomingHolder, @LayoutRes int outcomingLayout,
@NonNull ContentChecker contentChecker) {
if (type == 0)
throw new IllegalArgumentException("content type must be greater or less than '0'!");
customContentTypes.add(
new ContentTypeConfig<>(type,
new HolderConfig<>(incomingHolder, incomingLayout),
new HolderConfig<>(outcomingHolder, outcomingLayout)));
this.contentChecker = contentChecker;
return this;
}
/**
* Registers custom content type (e.g. multimedia, events etc.)
*
* @param type unique id for content type
* @param incomingHolder holder class for incoming message
* @param outcomingHolder holder class for outcoming message
* @param incomingPayload payload for incoming message
* @param outcomingPayload payload for outcoming message
* @param incomingLayout layout resource for incoming message
* @param outcomingLayout layout resource for outcoming message
* @param contentChecker {@link MessageHolders.ContentChecker} for registered type
* @return {@link MessageHolders} for subsequent configuration.
*/
public <TYPE extends MessageContentType>
MessageHolders registerContentType(
byte type,
@NonNull Class<? extends MessageHolders.BaseMessageViewHolder<TYPE>> incomingHolder, Object incomingPayload, @LayoutRes int incomingLayout,
@NonNull Class<? extends MessageHolders.BaseMessageViewHolder<TYPE>> outcomingHolder, Object outcomingPayload, @LayoutRes int outcomingLayout,
@NonNull MessageHolders.ContentChecker contentChecker) {
if (type == 0)
throw new IllegalArgumentException("content type must be greater or less than '0'!");
customContentTypes.add(
new MessageHolders.ContentTypeConfig<>(type,
new HolderConfig<>(incomingHolder, incomingLayout, incomingPayload),
new HolderConfig<>(outcomingHolder, outcomingLayout, outcomingPayload)));
this.contentChecker = contentChecker;
return this;
}
/*
* INTERFACES
* */
/**
* The interface, which contains logic for checking the availability of content.
*/
public interface ContentChecker<MESSAGE extends IMessage> {
/**
* Checks the availability of content.
*
* @param message current message in list.
* @param type content type, for which content availability is determined.
* @return weather the message has content for the current message.
*/
boolean hasContentFor(MESSAGE message, byte type);
}
/*
* PRIVATE METHODS
* */
protected ViewHolder getHolder(ViewGroup parent, int viewType, MessagesListStyle messagesListStyle) {
switch (viewType) {
case VIEW_TYPE_DATE_HEADER:
return getHolder(parent, dateHeaderLayout, dateHeaderHolder, messagesListStyle, null);
case VIEW_TYPE_STRING_HEADER:
return getHolder(parent, dateHeaderLayout, stringHeaderHolder, messagesListStyle, null);
case VIEW_TYPE_TEXT_MESSAGE:
return getHolder(parent, incomingTextConfig, messagesListStyle);
case -VIEW_TYPE_TEXT_MESSAGE:
return getHolder(parent, outcomingTextConfig, messagesListStyle);
case VIEW_TYPE_IMAGE_MESSAGE:
return getHolder(parent, incomingImageConfig, messagesListStyle);
case -VIEW_TYPE_IMAGE_MESSAGE:
return getHolder(parent, outcomingImageConfig, messagesListStyle);
default:
for (ContentTypeConfig typeConfig : customContentTypes) {
if (Math.abs(typeConfig.type) == Math.abs(viewType)) {
if (viewType > 0)
return getHolder(parent, typeConfig.incomingConfig, messagesListStyle);
else
return getHolder(parent, typeConfig.outcomingConfig, messagesListStyle);
}
}
}
throw new IllegalStateException("Wrong message view type. Please, report this issue on GitHub with full stacktrace in description.");
}
@SuppressWarnings("unchecked")
protected void bind(final ViewHolder holder, final Object item, boolean isSelected,
final ImageLoader imageLoader,
final View.OnClickListener onMessageClickListener,
final View.OnLongClickListener onMessageLongClickListener,
final View.OnFocusChangeListener onMessageFocusChangeListener,
final DateFormatter.Formatter dateHeadersFormatter,
final SparseArray<MessagesListAdapter.OnMessageViewClickListener> clickListenersArray) {
if (item instanceof IMessage) {
((MessageHolders.BaseMessageViewHolder) holder).isSelected = isSelected;
((MessageHolders.BaseMessageViewHolder) holder).imageLoader = imageLoader;
holder.itemView.setOnLongClickListener(onMessageLongClickListener);
holder.itemView.setOnClickListener(onMessageClickListener);
holder.itemView.setOnFocusChangeListener(onMessageFocusChangeListener);
for (int i = 0; i < clickListenersArray.size(); i++) {
final int key = clickListenersArray.keyAt(i);
final View view = holder.itemView.findViewById(key);
if (view != null) {
view.setOnClickListener(v -> clickListenersArray.get(key).onMessageViewClick(view, (IMessage) item));
}
}
} else if (item instanceof Date) {
((MessageHolders.DefaultDateHeaderViewHolder) holder).dateHeadersFormatter = dateHeadersFormatter;
}
holder.onBind(item);
}
protected int getViewType(Object item, String senderId) {
boolean isOutcoming = false;
int viewType;
if (item instanceof IMessage) {
IMessage message = (IMessage) item;
isOutcoming = message.getUser().getId().contentEquals(senderId);
viewType = getContentViewType(message);
} else if (item instanceof String) {
viewType = VIEW_TYPE_STRING_HEADER;
} else viewType = VIEW_TYPE_DATE_HEADER;
return isOutcoming ? viewType * -1 : viewType;
}
private ViewHolder getHolder(ViewGroup parent, HolderConfig holderConfig,
MessagesListStyle style) {
return getHolder(parent, holderConfig.layout, holderConfig.holder, style, holderConfig.payload);
}
private <HOLDER extends ViewHolder>
ViewHolder getHolder(ViewGroup parent, @LayoutRes int layout, Class<HOLDER> holderClass,
MessagesListStyle style, Object payload) {
View v = LayoutInflater.from(parent.getContext()).inflate(layout, parent, false);
try {
Constructor<HOLDER> constructor = null;
HOLDER holder;
try {
constructor = holderClass.getDeclaredConstructor(View.class, Object.class);
constructor.setAccessible(true);
holder = constructor.newInstance(v, payload);
} catch (NoSuchMethodException e) {
constructor = holderClass.getDeclaredConstructor(View.class);
constructor.setAccessible(true);
holder = constructor.newInstance(v);
}
if (holder instanceof DefaultMessageViewHolder && style != null) {
((DefaultMessageViewHolder) holder).applyStyle(style);
}
return holder;
} catch (Exception e) {
throw new UnsupportedOperationException("Somehow we couldn't create the ViewHolder for message. Please, report this issue on GitHub with full stacktrace in description.", e);
}
}
@SuppressWarnings("unchecked")
private short getContentViewType(IMessage message) {
if (message instanceof MessageContentType.Image
&& ((MessageContentType.Image) message).getImageUrl() != null) {
return VIEW_TYPE_IMAGE_MESSAGE;
}
// other default types will be here
if (message instanceof MessageContentType) {
for (int i = 0; i < customContentTypes.size(); i++) {
ContentTypeConfig config = customContentTypes.get(i);
if (contentChecker == null) {
throw new IllegalArgumentException("ContentChecker cannot be null when using custom content types!");
}
boolean hasContent = contentChecker.hasContentFor(message, config.type);
if (hasContent) return config.type;
}
}
return VIEW_TYPE_TEXT_MESSAGE;
}
/*
* HOLDERS
* */
/**
* The base class for view holders for incoming and outcoming message.
* You can extend it to create your own holder in conjuction with custom layout or even using default layout.
*/
public static abstract class BaseMessageViewHolder<MESSAGE extends IMessage> extends ViewHolder<MESSAGE> {
boolean isSelected;
/**
* For setting custom data to ViewHolder
*/
protected Object payload;
/**
* Callback for implementing images loading in message list
*/
protected ImageLoader imageLoader;
@Deprecated
public BaseMessageViewHolder(View itemView) {
super(itemView);
}
public BaseMessageViewHolder(View itemView, Object payload) {
super(itemView);
this.payload = payload;
}
/**
* Returns whether is item selected
*
* @return weather is item selected.
*/
public boolean isSelected() {
return isSelected;
}
/**
* Returns weather is selection mode enabled
*
* @return weather is selection mode enabled.
*/
public boolean isSelectionModeEnabled() {
return MessagesListAdapter.isSelectionModeEnabled;
}
/**
* Getter for {@link #imageLoader}
*
* @return image loader interface.
*/
public ImageLoader getImageLoader() {
return imageLoader;
}
protected void configureLinksBehavior(final TextView text) {
text.setLinksClickable(false);
text.setMovementMethod(new LinkMovementMethod() {
@Override
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
boolean result = false;
if (!MessagesListAdapter.isSelectionModeEnabled) {
result = super.onTouchEvent(widget, buffer, event);
}
itemView.onTouchEvent(event);
return result;
}
});
}
}
/**
* Default view holder implementation for incoming text message
*/
public static class IncomingTextMessageViewHolder<MESSAGE extends IMessage>
extends BaseIncomingMessageViewHolder<MESSAGE> {
protected ViewGroup bubble;
protected TextView text;
// See: item_incoming_text_message.xml
protected RelativeLayout wrapper;
@Deprecated
public IncomingTextMessageViewHolder(View itemView) {
super(itemView);
init(itemView);
}
public IncomingTextMessageViewHolder(View itemView, Object payload) {
super(itemView, payload);
init(itemView);
}
@Override
public void onBind(MESSAGE message) {
super.onBind(message);
if (bubble != null) {
bubble.setSelected(isSelected());
}
if (text != null) {
text.setText(message.getText());
}
}
@SuppressLint("WrongConstant")
@Override
public void applyStyle(MessagesListStyle style) {
super.applyStyle(style);
if (bubble != null) {
bubble.setPadding(style.getIncomingDefaultBubblePaddingLeft(),
style.getIncomingDefaultBubblePaddingTop(),
style.getIncomingDefaultBubblePaddingRight(),
style.getIncomingDefaultBubblePaddingBottom());
ViewCompat.setBackground(bubble, style.getIncomingBubbleDrawable());
}
if (text != null) {
text.setTextColor(style.getIncomingTextColor());
text.setTextSize(TypedValue.COMPLEX_UNIT_PX, style.getIncomingTextSize());
text.setTypeface(text.getTypeface(), style.getIncomingTextStyle());
text.setAutoLinkMask(style.getTextAutoLinkMask());
text.setLinkTextColor(style.getIncomingTextLinkColor());
// Link configurator makes textView focusable.
if (style.isMessageFocusable()) {
configureLinksBehavior(text);
//text.setFocusable(true);
//text.setFocusableInTouchMode(true);
//text.setClickable(true);
//text.setBackgroundResource(R.drawable.bgchange);
//text.requestFocus();
wrapper.setFocusable(true);
//wrapper.setFocusableInTouchMode(true);
//wrapper.setClickable(true);
//wrapper.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
//wrapper.requestFocus();
//wrapper.setBackgroundResource(R.drawable.bgchange);
//wrapper.setOnFocusChangeListener((v, hasFocus) -> {
// //text.setBackgroundResource(hasFocus ? R.color.tg_selected_bg : R.color.transparent);
// bubble.setBackgroundResource(hasFocus ? R.drawable.shape_incoming_message_focused : R.drawable.shape_incoming_message);
//});
}
}
}
private void init(View itemView) {
bubble = itemView.findViewById(R.id.bubble);
text = itemView.findViewById(R.id.messageText);
wrapper = (RelativeLayout) itemView;
}
}
/**
* Default view holder implementation for outcoming text message
*/
public static class OutcomingTextMessageViewHolder<MESSAGE extends IMessage>
extends BaseOutcomingMessageViewHolder<MESSAGE> {
protected ViewGroup bubble;
protected TextView text;
// See: item_outcoming_text_message.xml
protected RelativeLayout wrapper;
@Deprecated
public OutcomingTextMessageViewHolder(View itemView) {
super(itemView);
init(itemView);
}
public OutcomingTextMessageViewHolder(View itemView, Object payload) {
super(itemView, payload);
init(itemView);
}
@Override
public void onBind(MESSAGE message) {
super.onBind(message);
if (bubble != null) {
bubble.setSelected(isSelected());
}
if (text != null) {
text.setText(message.getText());
}
}
@SuppressLint("WrongConstant")
@Override
public final void applyStyle(MessagesListStyle style) {
super.applyStyle(style);
if (bubble != null) {
bubble.setPadding(style.getOutcomingDefaultBubblePaddingLeft(),
style.getOutcomingDefaultBubblePaddingTop(),
style.getOutcomingDefaultBubblePaddingRight(),
style.getOutcomingDefaultBubblePaddingBottom());
ViewCompat.setBackground(bubble, style.getOutcomingBubbleDrawable());
}
if (text != null) {
text.setTextColor(style.getOutcomingTextColor());
text.setTextSize(TypedValue.COMPLEX_UNIT_PX, style.getOutcomingTextSize());
text.setTypeface(text.getTypeface(), style.getOutcomingTextStyle());
text.setAutoLinkMask(style.getTextAutoLinkMask());
text.setLinkTextColor(style.getOutcomingTextLinkColor());
// Link configurator makes textView focusable.
if (style.isMessageFocusable()) {
configureLinksBehavior(text);
wrapper.setFocusable(true);
wrapper.setFocusableInTouchMode(true);
wrapper.setClickable(true);
wrapper.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
wrapper.requestFocus();
}
}
}
private void init(View itemView) {
bubble = itemView.findViewById(R.id.bubble);
text = itemView.findViewById(R.id.messageText);
wrapper = (RelativeLayout) itemView;
}
}
/**
* Default view holder implementation for incoming image message
*/
public static class IncomingImageMessageViewHolder<MESSAGE extends MessageContentType.Image>
extends BaseIncomingMessageViewHolder<MESSAGE> {
protected ImageView image;
protected View imageOverlay;
@Deprecated
public IncomingImageMessageViewHolder(View itemView) {
super(itemView);
init(itemView);
}
public IncomingImageMessageViewHolder(View itemView, Object payload) {
super(itemView, payload);
init(itemView);
}
@Override
public void onBind(MESSAGE message) {
super.onBind(message);
if (image != null && imageLoader != null) {
imageLoader.loadImage(image, message.getImageUrl(), getPayloadForImageLoader(message));
}
if (imageOverlay != null) {
imageOverlay.setSelected(isSelected());
}
}
@SuppressLint("WrongConstant")
@Override
public final void applyStyle(MessagesListStyle style) {
super.applyStyle(style);
if (time != null) {
time.setTextColor(style.getIncomingImageTimeTextColor());
time.setTextSize(TypedValue.COMPLEX_UNIT_PX, style.getIncomingImageTimeTextSize());
time.setTypeface(time.getTypeface(), style.getIncomingImageTimeTextStyle());
}
if (imageOverlay != null) {
ViewCompat.setBackground(imageOverlay, style.getIncomingImageOverlayDrawable());
}
}
/**
* Override this method to have ability to pass custom data in ImageLoader for loading image(not avatar).
*
* @param message Message with image
*/
protected Object getPayloadForImageLoader(MESSAGE message) {
return null;
}
private void init(View itemView) {
image = itemView.findViewById(R.id.image);
imageOverlay = itemView.findViewById(R.id.imageOverlay);
if (image instanceof RoundedImageView) {
((RoundedImageView) image).setCorners(
R.dimen.message_bubble_corners_radius,
R.dimen.message_bubble_corners_radius,
R.dimen.message_bubble_corners_radius,
0
);
}
}
}
/**
* Default view holder implementation for outcoming image message
*/
public static class OutcomingImageMessageViewHolder<MESSAGE extends MessageContentType.Image>
extends BaseOutcomingMessageViewHolder<MESSAGE> {
protected ImageView image;
protected View imageOverlay;
@Deprecated
public OutcomingImageMessageViewHolder(View itemView) {
super(itemView);
init(itemView);
}
public OutcomingImageMessageViewHolder(View itemView, Object payload) {
super(itemView, payload);
init(itemView);
}
@Override
public void onBind(MESSAGE message) {
super.onBind(message);
if (image != null && imageLoader != null) {
imageLoader.loadImage(image, message.getImageUrl(), getPayloadForImageLoader(message));
}
if (imageOverlay != null) {
imageOverlay.setSelected(isSelected());
}
}
@SuppressLint("WrongConstant")
@Override
public final void applyStyle(MessagesListStyle style) {
super.applyStyle(style);
if (time != null) {
time.setTextColor(style.getOutcomingImageTimeTextColor());
time.setTextSize(TypedValue.COMPLEX_UNIT_PX, style.getOutcomingImageTimeTextSize());
time.setTypeface(time.getTypeface(), style.getOutcomingImageTimeTextStyle());
}
if (imageOverlay != null) {
ViewCompat.setBackground(imageOverlay, style.getOutcomingImageOverlayDrawable());
}
}
/**
* Override this method to have ability to pass custom data in ImageLoader for loading image(not avatar).
*
* @param message Message with image
*/
protected Object getPayloadForImageLoader(MESSAGE message) {
return null;
}
private void init(View itemView) {
image = itemView.findViewById(R.id.image);
imageOverlay = itemView.findViewById(R.id.imageOverlay);
if (image instanceof RoundedImageView) {
((RoundedImageView) image).setCorners(
R.dimen.message_bubble_corners_radius,
R.dimen.message_bubble_corners_radius,
0,
R.dimen.message_bubble_corners_radius
);
}
}
}
/**
* Default view holder implementation for date header
*/
public static class DefaultDateHeaderViewHolder extends ViewHolder<Date>
implements DefaultMessageViewHolder {
protected TextView text;
protected String dateFormat;
protected DateFormatter.Formatter dateHeadersFormatter;
public DefaultDateHeaderViewHolder(View itemView) {
super(itemView);
text = itemView.findViewById(R.id.messageText);
}
@Override
public void onBind(Date date) {
if (text != null) {
String formattedDate = null;
if (dateHeadersFormatter != null) formattedDate = dateHeadersFormatter.format(date);
text.setText(formattedDate == null ? DateFormatter.format(date, dateFormat) : formattedDate);
}
}
@SuppressLint("WrongConstant")
@Override
public void applyStyle(MessagesListStyle style) {
if (text != null) {
text.setTextColor(style.getDateHeaderTextColor());
text.setTextSize(TypedValue.COMPLEX_UNIT_PX, style.getDateHeaderTextSize());
text.setTypeface(text.getTypeface(), style.getDateHeaderTextStyle());
text.setPadding(style.getDateHeaderPadding(), style.getDateHeaderPadding(),
style.getDateHeaderPadding(), style.getDateHeaderPadding());
}
dateFormat = style.getDateHeaderFormat();
dateFormat = dateFormat == null ? DateFormatter.Template.STRING_DAY_MONTH_YEAR.get() : dateFormat;
}
}
public static class DefaultStringHeaderViewHolder extends ViewHolder<String>
implements DefaultMessageViewHolder {
protected TextView text;
public DefaultStringHeaderViewHolder(View itemView) {
super(itemView);
text = itemView.findViewById(R.id.messageText);
}
@Override
public void onBind(String message) {
if (text != null) {
text.setText(message);
}
}
@SuppressLint("WrongConstant")
@Override
public void applyStyle(MessagesListStyle style) {
if (text != null) {
text.setTextColor(style.getDateHeaderTextColor());
text.setTextSize(TypedValue.COMPLEX_UNIT_PX, style.getDateHeaderTextSize());
text.setTypeface(text.getTypeface(), style.getDateHeaderTextStyle());
text.setPadding(style.getDateHeaderPadding(), style.getDateHeaderPadding(),
style.getDateHeaderPadding(), style.getDateHeaderPadding());
}
}
}
/**
* Base view holder for incoming message
*/
public abstract static class BaseIncomingMessageViewHolder<MESSAGE extends IMessage>
extends BaseMessageViewHolder<MESSAGE> implements DefaultMessageViewHolder {
protected TextView time;
protected ImageView userAvatar;
@Deprecated
public BaseIncomingMessageViewHolder(View itemView) {
super(itemView);
init(itemView);
}
public BaseIncomingMessageViewHolder(View itemView, Object payload) {
super(itemView, payload);
init(itemView);
}
@Override
public void onBind(MESSAGE message) {
if (time != null) {
time.setText(DateFormatter.format(message.getCreatedAt(), DateFormatter.Template.TIME));
}
if (userAvatar != null) {
boolean isAvatarExists = imageLoader != null
&& message.getUser().getAvatar() != null
&& !message.getUser().getAvatar().isEmpty();
userAvatar.setVisibility(isAvatarExists ? View.VISIBLE : View.GONE);
if (isAvatarExists) {
imageLoader.loadImage(userAvatar, message.getUser().getAvatar(), null);
}
}
}
@SuppressLint("WrongConstant")
@Override
public void applyStyle(MessagesListStyle style) {
if (time != null) {
time.setVisibility(style.showIncomingTime() ? View.VISIBLE : View.GONE);
time.setTextColor(style.getIncomingTimeTextColor());
time.setTextSize(TypedValue.COMPLEX_UNIT_PX, style.getIncomingTimeTextSize());
time.setTypeface(time.getTypeface(), style.getIncomingTimeTextStyle());
}
if (userAvatar != null) {
userAvatar.getLayoutParams().width = style.getIncomingAvatarWidth();
userAvatar.getLayoutParams().height = style.getIncomingAvatarHeight();
}
}
private void init(View itemView) {
time = itemView.findViewById(R.id.messageTime);
userAvatar = itemView.findViewById(R.id.messageUserAvatar);
}
}
/**
* Base view holder for outcoming message
*/
public abstract static class BaseOutcomingMessageViewHolder<MESSAGE extends IMessage>
extends BaseMessageViewHolder<MESSAGE> implements DefaultMessageViewHolder {
protected TextView time;
@Deprecated
public BaseOutcomingMessageViewHolder(View itemView) {
super(itemView);
init(itemView);
}
public BaseOutcomingMessageViewHolder(View itemView, Object payload) {
super(itemView, payload);
init(itemView);
}
@Override
public void onBind(MESSAGE message) {
if (time != null) {
time.setText(DateFormatter.format(message.getCreatedAt(), DateFormatter.Template.TIME));
}
}
@SuppressLint("WrongConstant")
@Override
public void applyStyle(MessagesListStyle style) {
if (time != null) {
time.setVisibility(style.showOutcomingTime() ? View.VISIBLE : View.GONE);
time.setTextColor(style.getOutcomingTimeTextColor());
time.setTextSize(TypedValue.COMPLEX_UNIT_PX, style.getOutcomingTimeTextSize());
time.setTypeface(time.getTypeface(), style.getOutcomingTimeTextStyle());
}
}
private void init(View itemView) {
time = itemView.findViewById(R.id.messageTime);
}
}
/*
* DEFAULTS
* */
interface DefaultMessageViewHolder {
void applyStyle(MessagesListStyle style);
}
private static class DefaultIncomingTextMessageViewHolder
extends IncomingTextMessageViewHolder<IMessage> {
public DefaultIncomingTextMessageViewHolder(View itemView) {
super(itemView, null);
}
}
private static class DefaultOutcomingTextMessageViewHolder
extends OutcomingTextMessageViewHolder<IMessage> {
public DefaultOutcomingTextMessageViewHolder(View itemView) {
super(itemView, null);
}
}
private static class DefaultIncomingImageMessageViewHolder
extends IncomingImageMessageViewHolder<MessageContentType.Image> {
public DefaultIncomingImageMessageViewHolder(View itemView) {
super(itemView, null);
}
}
private static class DefaultOutcomingImageMessageViewHolder
extends OutcomingImageMessageViewHolder<MessageContentType.Image> {
public DefaultOutcomingImageMessageViewHolder(View itemView) {
super(itemView, null);
}
}
private static class ContentTypeConfig<TYPE extends MessageContentType> {
private byte type;
private HolderConfig<TYPE> incomingConfig;
private HolderConfig<TYPE> outcomingConfig;
private ContentTypeConfig(
byte type, HolderConfig<TYPE> incomingConfig, HolderConfig<TYPE> outcomingConfig) {
this.type = type;
this.incomingConfig = incomingConfig;
this.outcomingConfig = outcomingConfig;
}
}
private static class HolderConfig<T extends IMessage> {
protected Class<? extends BaseMessageViewHolder<? extends T>> holder;
protected int layout;
protected Object payload;
HolderConfig(Class<? extends BaseMessageViewHolder<? extends T>> holder, int layout) {
this.holder = holder;
this.layout = layout;
}
HolderConfig(Class<? extends BaseMessageViewHolder<? extends T>> holder, int layout, Object payload) {
this.holder = holder;
this.layout = layout;
this.payload = payload;
}
}
}
================================================
FILE: chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageInput.java
================================================
/*******************************************************************************
* Copyright 2016 stfalcon.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.stfalcon.chatkit.messages;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.RelativeLayout;
import android.widget.Space;
import android.widget.TextView;
import androidx.core.view.ViewCompat;
import com.stfalcon.chatkit.R;
import java.lang.reflect.Field;
/**
* Component for input outcoming messages
*/
@SuppressWarnings({"WeakerAccess", "unused"})
public class MessageInput extends RelativeLayout
implements View.OnClickListener, TextWatcher, View.OnFocusChangeListener {
protected EditText messageInput;
protected ImageButton messageSendButton;
protected ImageButton attachmentButton;
protected Space sendButtonSpace, attachmentButtonSpace;
private CharSequence input;
private InputListener inputListener;
private AttachmentsListener attachmentsListener;
private boolean isTyping;
private TypingListener typingListener;
private int delayTypingStatusMillis;
private Runnable typingTimerRunnable = new Runnable() {
@Override
public void run() {
if (isTyping) {
isTyping = false;
if (typingListener != null) typingListener.onStopTyping();
}
}
};
private boolean lastFocus;
public MessageInput(Context context) {
super(context);
init(context);
}
public MessageInput(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public MessageInput(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
/**
* Sets callback for 'submit' button.
*
* @param inputListener input callback
*/
public void setInputListener(InputListener inputListener) {
this.inputListener = inputListener;
}
/**
* Sets callback for 'add' button.
*
* @param attachmentsListener input callback
*/
public void setAttachmentsListener(AttachmentsListener attachmentsListener) {
this.attachmentsListener = attachmentsListener;
}
/**
* Returns EditText for messages input
*
* @return EditText
*/
public EditText getInputEditText() {
return messageInput;
}
/**
* Returns `submit` button
*
* @return ImageButton
*/
public ImageButton getButton() {
return messageSendButton;
}
@Override
public void onClick(View view) {
int id = view.getId();
if (id == R.id.messageSendButton) {
boolean isSubmitted = onSubmit();
if (isSubmitted) {
messageInput.setText("");
}
removeCallbacks(typingTimerRunnable);
post(typingTimerRunnable);
} else if (id == R.id.attachmentButton) {
onAddAttachments();
}
}
/**
* This method is called to notify you that, within s,
* the count characters beginning at start have just replaced old text that had length before
*/
@Override
public void onTextChanged(CharSequence s, int start, int count, int after) {
input = s;
messageSendButton.setEnabled(input.length() > 0);
if (s.length() > 0) {
if (!isTyping) {
isTyping = true;
if (typingListener != null) typingListener.onStartTyping();
}
removeCallbacks(typingTimerRunnable);
postDelayed(typingTimerRunnable, delayTypingStatusMillis);
}
}
/**
* This method is called to notify you that, within s,
* the count characters beginning at start are about to be replaced by new text with length after.
*/
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
//do nothing
}
/**
* This method is called to notify you that, somewhere within s, the text has been changed.
*/
@Override
public void afterTextChanged(Editable editable) {
//do nothing
}
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (lastFocus && !hasFocus && typingListener != null) {
typingListener.onStopTyping();
}
lastFocus = hasFocus;
}
private boolean onSubmit() {
return inputListener != null && inputListener.onSubmit(input);
}
private void onAddAttachments() {
if (attachmentsListener != null) attachmentsListener.onAddAttachments();
}
private void init(Context context, AttributeSet attrs) {
init(context);
MessageInputStyle style = MessageInputStyle.parse(context, attrs);
this.messageInput.setMaxLines(style.getInputMaxLines());
this.messageInput.setHint(style.getInputHint());
this.messageInput.setText(style.getInputText());
this.messageInput.setTextSize(TypedValue.COMPLEX_UNIT_PX, style.getInputTextSize());
this.messageInput.setTextColor(style.getInputTextColor());
this.messageInput.setHintTextColor(style.getInputHintColor());
ViewCompat.setBackground(this.messageInput, style.getInputBackground());
setCursor(style.getInputCursorDrawable());
this.attachmentButton.setVisibility(style.showAttachmentButton() ? VISIBLE : GONE);
this.attachmentButton.setImageDrawable(style.getAttachmentButtonIcon());
this.attachmentButton.getLayoutParams().width = style.getAttachmentButtonWidth();
this.attachmentButton.getLayoutParams().height = style.getAttachmentButtonHeight();
ViewCompat.setBackground(this.attachmentButton, style.getAttachmentButtonBackground());
this.attachmentButtonSpace.setVisibility(style.showAttachmentButton() ? VISIBLE : GONE);
this.attachmentButtonSpace.getLayoutParams().width = style.getAttachmentButtonMargin();
this.messageSendButton.setImageDrawable(style.getInputButtonIcon());
this.messageSendButton.getLayoutParams().width = style.getInputButtonWidth();
this.messageSendButton.getLayoutParams().height = style.getInputButtonHeight();
ViewCompat.setBackground(messageSendButton, style.getInputButtonBackground());
this.sendButtonSpace.getLayoutParams().width = style.getInputButtonMargin();
if (getPaddingLeft() == 0
&& getPaddingRight() == 0
&& getPaddingTop() == 0
&& getPaddingBottom() == 0) {
setPadding(
style.getInputDefaultPaddingLeft(),
style.getInputDefaultPaddingTop(),
style.getInputDefaultPaddingRight(),
style.getInputDefaultPaddingBottom()
);
}
this.delayTypingStatusMillis = style.getDelayTypingStatus();
}
private void init(Context context) {
inflate(context, R.layout.view_message_input, this);
messageInput = findViewById(R.id.messageInput);
messageSendButton = findViewById(R.id.messageSendButton);
attachmentButton = findViewById(R.id.attachmentButton);
sendButtonSpace = findViewById(R.id.sendButtonSpace);
attachmentButtonSpace = findViewById(R.id.attachmentButtonSpace);
messageSendButton.setOnClickListener(this);
attachmentButton.setOnClickListener(this);
messageInput.addTextChangedListener(this);
messageInput.setText("");
messageInput.setOnFocusChangeListener(this);
}
private void setCursor(Drawable drawable) {
if (drawable == null) return;
try {
final Field drawableResField = TextView.class.getDeclaredField("mCursorDrawableRes");
drawableResField.setAccessible(true);
final Object drawableFieldOwner;
final Class<?> drawableFieldClass;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
drawableFieldOwner = this.messageInput;
drawableFieldClass = TextView.class;
} else {
final Field editorField = TextView.class.getDeclaredField("mEditor");
editorField.setAccessible(true);
drawableFieldOwner = editorField.get(this.messageInput);
drawableFieldClass = drawableFieldOwner.getClass();
}
final Field drawableField = drawableFieldClass.getDeclaredField("mCursorDrawable");
drawableField.setAccessible(true);
drawableField.set(drawableFieldOwner, new Drawable[]{drawable, drawable});
} catch (Exception ignored) {
}
}
public void setTypingListener(TypingListener typingListener) {
this.typingListener = typingListener;
}
/**
* Interface definition for a callback to be invoked when user pressed 'submit' button
*/
public interface InputListener {
/**
* Fires when user presses 'send' button.
*
* @param input input entered by user
* @return if input text is valid, you must return {@code true} and input will be cleared, otherwise return false.
*/
boolean onSubmit(CharSequence input);
}
/**
* Interface definition for a callback to be invoked when user presses 'add' button
*/
public interface AttachmentsListener {
/**
* Fires when user presses 'add' button.
*/
void onAddAttachments();
}
/**
* Interface definition for a callback to be invoked when user typing
*/
public interface TypingListener {
/**
* Fires when user presses start typing
*/
void onStartTyping();
/**
* Fires when user presses stop typing
*/
void onStopTyping();
}
}
================================================
FILE: chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageInputStyle.java
================================================
/*******************************************************************************
* Copyright 2016 stfalcon.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.stfalcon.chatkit.messages;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import androidx.annotation.ColorInt;
import androidx.annotation.DrawableRes;
import androidx.core.graphics.drawable.DrawableCompat;
import com.stfalcon.chatkit.R;
import com.stfalcon.chatkit.commons.Style;
/**
* Style for MessageInputStyle customization by xml attributes
*/
@SuppressWarnings("WeakerAccess")
class MessageInputStyle extends Style {
private static final int DEFAULT_MAX_LINES = 5;
private static final int DEFAULT_DELAY_TYPING_STATUS = 1500;
private boolean showAttachmentButton;
private int attachmentButtonBackground;
private int attachmentButtonDefaultBgColor;
private int attachmentButtonDefaultBgPressedColor;
private int attachmentButtonDefaultBgDisabledColor;
private int attachmentButtonIcon;
private int attachmentButtonDefaultIconColor;
private int attachmentButtonDefaultIconPressedColor;
private int attachmentButtonDefaultIconDisabledColor;
private int attachmentButtonWidth;
private int attachmentButtonHeight;
private int attachmentButtonMargin;
private int inputButtonBackground;
private int inputButtonDefaultBgColor;
private int inputButtonDefaultBgPressedColor;
private int inputButtonDefaultBgDisabledColor;
private int inputButtonIcon;
private int inputButtonDefaultIconColor;
private int inputButtonDefaultIconPressedColor;
private int inputButtonDefaultIconDisabledColor;
private int inputButtonWidth;
private int inputButtonHeight;
private int inputButtonMargin;
private int inputMaxLines;
private String inputHint;
private String inputText;
private int inputTextSize;
private int inputTextColor;
private int inputHintColor;
private Drawable inputBackground;
private Drawable inputCursorDrawable;
private int inputDefaultPaddingLeft;
private int inputDefaultPaddingRight;
private int inputDefaultPaddingTop;
private int inputDefaultPaddingBottom;
private int delayTypingStatus;
static MessageInputStyle parse(Context context, AttributeSet attrs) {
MessageInputStyle style = new MessageInputStyle(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MessageInput);
style.showAttachmentButton = typedArray.getBoolean(R.styleable.MessageInput_showAttachmentButton, false);
style.attachmentButtonBackground = typedArray.getResourceId(R.styleable.MessageInput_attachmentButtonBackground, -1);
style.attachmentButtonDefaultBgColor = typedArray.getColor(R.styleable.MessageInput_attachmentButtonDefaultBgColor,
style.getColor(R.color.white_four));
style.attachmentButtonDefaultBgPressedColor = typedArray.getColor(R.styleable.MessageInput_attachmentButtonDefaultBgPressedColor,
style.getColor(R.color.white_five));
style.attachmentButtonDefaultBgDisabledColor = typedArray.getColor(R.styleable.MessageInput_attachmentButtonDefaultBgDisabledColor,
style.getColor(R.color.transparent));
style.attachmentButtonIcon = typedArray.getResourceId(R.styleable.MessageInput_attachmentButtonIcon, -1);
style.attachmentButtonDefaultIconColor = typedArray.getColor(R.styleable.MessageInput_attachmentButtonDefaultIconColor,
style.getColor(R.color.cornflower_blue_two));
style.attachmentButtonDefaultIconPressedColor = typedArray.getColor(R.styleable.MessageInput_attachmentButtonDefaultIconPressedColor,
style.getColor(R.color.cornflower_blue_two_dark));
style.attachmentButtonDefaultIconDisabledColor = typedArray.getColor(R.styleable.MessageInput_attachmentButtonDefaultIconDisabledColor,
style.getColor(R.color.cornflower_blue_light_40));
style.attachmentButtonWidth = typedArray.getDimensionPixelSize(R.styleable.MessageInput_attachmentButtonWidth, style.getDimension(R.dimen.input_button_width));
style.attachmentButtonHeight = typedArray.getDimensionPixelSize(R.styleable.MessageInput_attachmentButtonHeight, style.getDimension(R.dimen.input_button_height));
style.attachmentButtonMargin = typedArray.getDimensionPixelSize(R.styleable.MessageInput_attachmentButtonMargin, style.getDimension(R.dimen.input_button_margin));
style.inputButtonBackground = typedArray.getResourceId(R.styleable.MessageInput_inputButtonBackground, -1);
style.inputButtonDefaultBgColor = typedArray.getColor(R.styleable.MessageInput_inputButtonDefaultBgColor,
style.getColor(R.color.cornflower_blue_two));
style.inputButtonDefaultBgPressedColor = typedArray.getColor(R.styleable.MessageInput_inputButtonDefaultBgPressedColor,
style.getColor(R.color.cornflower_blue_two_dark));
style.inputButtonDefaultBgDisabledColor = typedArray.getColor(R.styleable.MessageInput_inputButtonDefaultBgDisabledColor,
style.getColor(R.color.white_four));
style.inputButtonIcon = typedArray.getResourceId(R.styleable.MessageInput_inputButtonIcon, -1);
style.inputButtonDefaultIconColor = typedArray.getColor(R.styleable.MessageInput_inputButtonDefaultIconColor,
style.getColor(R.color.white));
style.inputButtonDefaultIconPressedColor = typedArray.getColor(R.styleable.MessageInput_inputButtonDefaultIconPressedColor,
style.getColor(R.color.white));
style.inputButtonDefaultIconDisabledColor = typedArray.getColor(R.styleable.MessageInput_inputButtonDefaultIconDisabledColor,
style.getColor(R.color.warm_grey));
style.inputButtonWidth = typedArray.getDimensionPixelSize(R.styleable.MessageInput_inputButtonWidth, style.getDimension(R.dimen.input_button_width));
style.inputButtonHeight = typedArray.getDimensionPixelSize(R.styleable.MessageInput_inputButtonHeight, style.getDimension(R.dimen.input_button_height));
style.inputButtonMargin = typedArray.getDimensionPixelSize(R.styleable.MessageInput_inputButtonMargin, style.getDimension(R.dimen.input_button_margin));
style.inputMaxLines = typedArray.getInt(R.styleable.MessageInput_inputMaxLines, DEFAULT_MAX_LINES);
style.inputHint = typedArray.getString(R.styleable.MessageInput_inputHint);
style.inputText = typedArray.getString(R.styleable.MessageInput_inputText);
style.inputTextSize = typedArray.getDimensionPixelSize(R.styleable.MessageInput_inputTextSize, style.getDimension(R.dimen.input_text_size));
style.inputTextColor = typedArray.getColor(R.styleable.MessageInput_inputTextColor, style.getColor(R.color.dark_grey_two));
style.inputHintColor = typedArray.getColor(R.styleable.MessageInput_inputHintColor, style.getColor(R.color.warm_grey_three));
style.inputBackground = typedArray.getDrawable(R.styleable.MessageInput_inputBackground);
style.inputCursorDrawable = typedArray.getDrawable(R.styleable.MessageInput_inputCursorDrawable);
style.delayTypingStatus = typedArray.getInt(R.styleable.MessageInput_delayTypingStatus, DEFAULT_DELAY_TYPING_STATUS);
typedArray.recycle();
style.inputDefaultPaddingLeft = style.getDimension(R.dimen.input_padding_left);
style.inputDefaultPaddingRight = style.getDimension(R.dimen.input_padding_right);
style.inputDefaultPaddingTop = style.getDimension(R.dimen.input_padding_top);
style.inputDefaultPaddingBottom = style.getDimension(R.dimen.input_padding_bottom);
return style;
}
private MessageInputStyle(Context context, AttributeSet attrs) {
super(context, attrs);
}
private Drawable getSelector(@ColorInt int normalColor, @ColorInt int pressedColor,
@ColorInt int disabledColor, @DrawableRes int shape) {
Drawable drawable = DrawableCompat.wrap(getVectorDrawable(shape)).mutate();
DrawableCompat.setTintList(
drawable,
new ColorStateList(
new int[][]{
new int[]{android.R.attr.state_enabled, -android.R.attr.state_pressed},
new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed},
new int[]{-android.R.attr.state_enabled}
},
new int[]{normalColor, pressedColor, disabledColor}
));
return drawable;
}
protected boolean showAttachmentButton() {
return showAttachmentButton;
}
protected Drawable getAttachmentButtonBackground() {
if (attachmentButtonBackground == -1) {
return getSelector(attachmentButtonDefaultBgColor, attachmentButtonDefaultBgPressedColor,
attachmentButtonDefaultBgDisabledColor, R.drawable.mask);
} else {
return getDrawable(attachmentButtonBackground);
}
}
protected Drawable getAttachmentButtonIcon() {
if (attachmentButtonIcon == -1) {
return getSelector(attachmentButtonDefaultIconColor, attachmentButtonDefaultIconPressedColor,
attachmentButtonDefaultIconDisabledColor, R.drawable.ic_add_attachment);
} else {
return getDrawable(attachmentButtonIcon);
}
}
protected int getAttachmentButtonWidth() {
return
Showing preview only (215K chars total). Download the full file or copy to clipboard to get everything.
gitextract_iykr0_hr/
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── 1-bug_report.yml
│ │ ├── 2-feature-request.yml
│ │ └── config.yml
│ └── workflows/
│ ├── CI.yml
│ ├── cleanup.yml
│ ├── stale.yml
│ └── virustotal_scan.yml
├── .gitignore
├── .gitmodules
├── .reuse/
│ └── dep5
├── LICENSE
├── README.md
├── build.gradle
├── chatkit/
│ ├── .gitignore
│ ├── LICENSE
│ ├── build.gradle
│ ├── proguard.txt
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── com/
│ │ └── stfalcon/
│ │ └── chatkit/
│ │ ├── commons/
│ │ │ ├── DebouncedOnClickListener.java
│ │ │ ├── ImageLoader.java
│ │ │ ├── InputTrackingRecyclerViewAdapter.java
│ │ │ ├── Style.java
│ │ │ ├── ViewHolder.java
│ │ │ ├── models/
│ │ │ │ ├── IDialog.java
│ │ │ │ ├── IMessage.java
│ │ │ │ ├── IUser.java
│ │ │ │ └── MessageContentType.java
│ │ │ └── widgets/
│ │ │ ├── FocusFixRelativeLayout.java
│ │ │ └── WrapWidthTextView.java
│ │ ├── dialogs/
│ │ │ ├── DialogListStyle.java
│ │ │ ├── DialogsList.java
│ │ │ └── DialogsListAdapter.java
│ │ ├── messages/
│ │ │ ├── MessageHolders.java
│ │ │ ├── MessageInput.java
│ │ │ ├── MessageInputStyle.java
│ │ │ ├── MessagesList.java
│ │ │ ├── MessagesListAdapter.java
│ │ │ ├── MessagesListStyle.java
│ │ │ └── RecyclerScrollMoreListener.java
│ │ └── utils/
│ │ ├── DateFormatter.java
│ │ ├── RoundedImageView.java
│ │ └── ShapeImageView.java
│ └── res/
│ ├── color/
│ │ └── textchange.xml
│ ├── drawable/
│ │ ├── bgchange.xml
│ │ ├── bubble_circle.xml
│ │ ├── shape_incoming_message.xml
│ │ ├── shape_incoming_message_focused.xml
│ │ └── shape_outcoming_message.xml
│ ├── layout/
│ │ ├── item_date_header.xml
│ │ ├── item_dialog.xml
│ │ ├── item_incoming_image_message.xml
│ │ ├── item_incoming_text_message.xml
│ │ ├── item_outcoming_image_message.xml
│ │ ├── item_outcoming_text_message.xml
│ │ └── view_message_input.xml
│ ├── values/
│ │ ├── attrs.xml
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── fonts.xml
│ │ ├── ids.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── values-v21/
│ └── fonts.xml
├── common/
│ ├── .gitignore
│ ├── build.gradle
│ ├── consumer-rules.pro
│ ├── proguard-rules.pro
│ └── src/
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── liskovsoft/
│ │ │ └── smartyoutubetv2/
│ │ │ └── common/
│ │ │ ├── app/
│ │ │ │ ├── models/
│ │ │ │ │ ├── data/
│ │ │ │ │ │ ├── BrowseSection.java
│ │ │ │ │ │ ├── Playlist.java
│ │ │ │ │ │ ├── SettingsGroup.java
│ │ │ │ │ │ ├── SettingsItem.java
│ │ │ │ │ │ ├── SimpleMediaItem.java
│ │ │ │ │ │ ├── Video.java
│ │ │ │ │ │ └── VideoGroup.java
│ │ │ │ │ ├── errors/
│ │ │ │ │ │ ├── CategoryEmptyError.java
│ │ │ │ │ │ ├── ErrorFragmentData.java
│ │ │ │ │ │ ├── PasswordError.java
│ │ │ │ │ │ └── SignInError.java
│ │ │ │ │ ├── playback/
│ │ │ │ │ │ ├── BasePlayerController.java
│ │ │ │ │ │ ├── controllers/
│ │ │ │ │ │ │ ├── AutoFrameRateController.java
│ │ │ │ │ │ │ ├── ChatController.java
│ │ │ │ │ │ │ ├── CommentsController.java
│ │ │ │ │ │ │ ├── HQDialogController.java
│ │ │ │ │ │ │ ├── PlayerUIController.java
│ │ │ │ │ │ │ ├── RemoteController.java
│ │ │ │ │ │ │ ├── SponsorBlockController.java
│ │ │ │ │ │ │ ├── SuggestionsController.java
│ │ │ │ │ │ │ ├── VideoLoaderController.java
│ │ │ │ │ │ │ └── VideoStateController.java
│ │ │ │ │ │ ├── listener/
│ │ │ │ │ │ │ ├── PlayerEngineEventListener.java
│ │ │ │ │ │ │ ├── PlayerEventListener.java
│ │ │ │ │ │ │ ├── PlayerUiEventListener.java
│ │ │ │ │ │ │ └── ViewEventListener.java
│ │ │ │ │ │ ├── manager/
│ │ │ │ │ │ │ ├── PlayerConstants.java
│ │ │ │ │ │ │ ├── PlayerEngine.java
│ │ │ │ │ │ │ ├── PlayerManager.java
│ │ │ │ │ │ │ └── PlayerUI.java
│ │ │ │ │ │ ├── service/
│ │ │ │ │ │ │ └── VideoStateService.java
│ │ │ │ │ │ └── ui/
│ │ │ │ │ │ ├── AbstractCommentsReceiver.java
│ │ │ │ │ │ ├── ChatReceiver.java
│ │ │ │ │ │ ├── ChatReceiverImpl.java
│ │ │ │ │ │ ├── CommentsReceiver.java
│ │ │ │ │ │ ├── OptionCallback.java
│ │ │ │ │ │ ├── OptionCategory.java
│ │ │ │ │ │ ├── OptionItem.java
│ │ │ │ │ │ ├── SeekBarSegment.java
│ │ │ │ │ │ └── UiOptionItem.java
│ │ │ │ │ └── search/
│ │ │ │ │ ├── MediaServiceSearchTagProvider.java
│ │ │ │ │ ├── PrefsSearchTagsProvider.java
│ │ │ │ │ ├── SearchTagsProvider.java
│ │ │ │ │ └── vineyard/
│ │ │ │ │ ├── Option.java
│ │ │ │ │ ├── Tag.java
│ │ │ │ │ └── User.java
│ │ │ │ ├── presenters/
│ │ │ │ │ ├── AddDevicePresenter.java
│ │ │ │ │ ├── AppDialogPresenter.java
│ │ │ │ │ ├── BrowsePresenter.java
│ │ │ │ │ ├── ChannelPresenter.java
│ │ │ │ │ ├── ChannelUploadsPresenter.java
│ │ │ │ │ ├── DetailsPresenter.java
│ │ │ │ │ ├── GoogleSignInPresenter.java
│ │ │ │ │ ├── PlaybackPresenter.java
│ │ │ │ │ ├── SearchPresenter.java
│ │ │ │ │ ├── SignInPresenter.java
│ │ │ │ │ ├── SplashPresenter.java
│ │ │ │ │ ├── WebBrowserPresenter.java
│ │ │ │ │ ├── YTSignInPresenter.java
│ │ │ │ │ ├── base/
│ │ │ │ │ │ └── BasePresenter.java
│ │ │ │ │ ├── dialogs/
│ │ │ │ │ │ ├── ATVBridgePresenter.java
│ │ │ │ │ │ ├── AccountSelectionPresenter.java
│ │ │ │ │ │ ├── AmazonBridgePresenter.java
│ │ │ │ │ │ ├── AppUpdatePresenter.java
│ │ │ │ │ │ ├── BootDialogPresenter.java
│ │ │ │ │ │ ├── BridgePresenter.java
│ │ │ │ │ │ ├── QuickRestorePresenter.java
│ │ │ │ │ │ ├── StableRestorePresenter.java
│ │ │ │ │ │ ├── VideoActionPresenter.java
│ │ │ │ │ │ └── menu/
│ │ │ │ │ │ ├── BaseMenuPresenter.java
│ │ │ │ │ │ ├── ChannelUploadsMenuPresenter.java
│ │ │ │ │ │ ├── SectionMenuPresenter.java
│ │ │ │ │ │ ├── VideoMenuPresenter.java
│ │ │ │ │ │ └── providers/
│ │ │ │ │ │ ├── ContextMenuManager.java
│ │ │ │ │ │ ├── ContextMenuProvider.java
│ │ │ │ │ │ └── channelgroup/
│ │ │ │ │ │ ├── ChannelGroupMenuProvider.java
│ │ │ │ │ │ ├── ChannelGroupServiceWrapper.java
│ │ │ │ │ │ ├── RemoveGroupMenuProvider.java
│ │ │ │ │ │ └── RenameGroupMenuProvider.java
│ │ │ │ │ ├── interfaces/
│ │ │ │ │ │ ├── Presenter.java
│ │ │ │ │ │ ├── SectionPresenter.java
│ │ │ │ │ │ └── VideoGroupPresenter.java
│ │ │ │ │ ├── service/
│ │ │ │ │ │ └── SidebarService.java
│ │ │ │ │ └── settings/
│ │ │ │ │ ├── AboutSettingsPresenter.java
│ │ │ │ │ ├── AboutSimpleSettingsPresenter.java
│ │ │ │ │ ├── AccountSettingsPresenter.java
│ │ │ │ │ ├── AutoFrameRateSettingsPresenter.java
│ │ │ │ │ ├── BackupSettingsPresenter.java
│ │ │ │ │ ├── DeArrowSettingsPresenter.java
│ │ │ │ │ ├── GeneralSettingsPresenter.java
│ │ │ │ │ ├── LanguageSettingsPresenter.java
│ │ │ │ │ ├── MainUISettingsPresenter.java
│ │ │ │ │ ├── PlayerSettingsPresenter.java
│ │ │ │ │ ├── RemoteControlSettingsPresenter.java
│ │ │ │ │ ├── SearchSettingsPresenter.java
│ │ │ │ │ ├── SponsorBlockSettingsPresenter.java
│ │ │ │ │ ├── SubtitleSettingsPresenter.java
│ │ │ │ │ └── UIScaleSettingsPresenter.java
│ │ │ │ └── views/
│ │ │ │ ├── AddDeviceView.java
│ │ │ │ ├── AppDialogView.java
│ │ │ │ ├── AppUpdateView.java
│ │ │ │ ├── BrowseView.java
│ │ │ │ ├── ChannelUploadsView.java
│ │ │ │ ├── ChannelView.java
│ │ │ │ ├── DetailsView.java
│ │ │ │ ├── PlaybackView.java
│ │ │ │ ├── SearchView.java
│ │ │ │ ├── SignInView.java
│ │ │ │ ├── SplashView.java
│ │ │ │ ├── ViewManager.java
│ │ │ │ └── WebBrowserView.java
│ │ │ ├── autoframerate/
│ │ │ │ ├── AutoFrameRateHelper.java
│ │ │ │ ├── ModeSyncManager.java
│ │ │ │ └── internal/
│ │ │ │ ├── DisplayHolder.java
│ │ │ │ ├── DisplaySyncHelper.java
│ │ │ │ ├── UhdHelper.java
│ │ │ │ └── UhdHelperListener.java
│ │ │ ├── exoplayer/
│ │ │ │ ├── ExoMediaSourceFactory.java
│ │ │ │ ├── LiveDashManifestParser.java
│ │ │ │ ├── controller/
│ │ │ │ │ ├── ExoPlayerController.java
│ │ │ │ │ └── PlayerView.java
│ │ │ │ ├── errors/
│ │ │ │ │ ├── DashDefaultLoadErrorHandlingPolicy.java
│ │ │ │ │ ├── SabrDefaultLoadErrorHandlingPolicy.java
│ │ │ │ │ └── TrackErrorFixer.java
│ │ │ │ ├── other/
│ │ │ │ │ ├── DebugInfoManager.java
│ │ │ │ │ ├── ExoPlayerInitializer.java
│ │ │ │ │ ├── SubtitleManager.java
│ │ │ │ │ ├── VideoZoomManager.java
│ │ │ │ │ └── VolumeBooster.java
│ │ │ │ ├── selector/
│ │ │ │ │ ├── ExoFormatItem.java
│ │ │ │ │ ├── FormatItem.java
│ │ │ │ │ ├── TrackInfoFormatter2.java
│ │ │ │ │ ├── TrackSelectorManager.java
│ │ │ │ │ ├── TrackSelectorUtil.java
│ │ │ │ │ └── track/
│ │ │ │ │ ├── AudioTrack.java
│ │ │ │ │ ├── MediaTrack.java
│ │ │ │ │ ├── SubtitleTrack.java
│ │ │ │ │ └── VideoTrack.java
│ │ │ │ └── versions/
│ │ │ │ ├── ExoUtils.java
│ │ │ │ ├── renderer/
│ │ │ │ │ ├── CustomOverridesRenderersFactory.java
│ │ │ │ │ ├── CustomRenderersFactoryBase.java
│ │ │ │ │ ├── DebugInfoMediaCodecVideoRenderer.java
│ │ │ │ │ ├── DelayMediaCodecAudioRenderer.java
│ │ │ │ │ └── TweaksMediaCodecVideoRenderer.java
│ │ │ │ └── selector/
│ │ │ │ ├── BlacklistMediaCodecSelector.java
│ │ │ │ ├── RestoreTrackSelector.java
│ │ │ │ └── backport/
│ │ │ │ └── Definition.java
│ │ │ ├── misc/
│ │ │ │ ├── AppDataSourceManager.java
│ │ │ │ ├── BackgroundPlaybackService.java
│ │ │ │ ├── BackupAndRestoreHelper.java
│ │ │ │ ├── BackupAndRestoreManager.java
│ │ │ │ ├── BackupReceiverActivity.java
│ │ │ │ ├── BrowseProcessor.java
│ │ │ │ ├── BrowseProcessorManager.java
│ │ │ │ ├── CrashRestorer.java
│ │ │ │ ├── DeArrowProcessor.java
│ │ │ │ ├── GDriveBackupManager.java
│ │ │ │ ├── GDriveBackupManagerOld.java
│ │ │ │ ├── GDriveBackupWorker.java
│ │ │ │ ├── GlobalKeyTranslator.java
│ │ │ │ ├── KeyTranslator.java
│ │ │ │ ├── LocalDriveBackupWorker.java
│ │ │ │ ├── MediaServiceManager.java
│ │ │ │ ├── MotherActivity.java
│ │ │ │ ├── PlayerKeyTranslator.java
│ │ │ │ ├── RemoteControlReceiver.java
│ │ │ │ ├── RemoteControlService.java
│ │ │ │ ├── RemoteControlWorker.java
│ │ │ │ ├── ScreensaverManager.java
│ │ │ │ ├── SharedPreferencesHelper.java
│ │ │ │ ├── StreamReminderService.java
│ │ │ │ ├── TickleManager.java
│ │ │ │ ├── UnlocalizedTitleProcessor.java
│ │ │ │ ├── ZipHelper.java
│ │ │ │ └── ZipHelper2.java
│ │ │ ├── prefs/
│ │ │ │ ├── AccountsData.java
│ │ │ │ ├── AppPrefs.java
│ │ │ │ ├── BlockedChannelData.java
│ │ │ │ ├── DeArrowData.java
│ │ │ │ ├── GeneralData.java
│ │ │ │ ├── HiddenPrefs.java
│ │ │ │ ├── MainUIData.java
│ │ │ │ ├── PlayerData.java
│ │ │ │ ├── PlayerTweaksData.java
│ │ │ │ ├── RemoteControlData.java
│ │ │ │ ├── SearchData.java
│ │ │ │ ├── SponsorBlockData.java
│ │ │ │ └── common/
│ │ │ │ ├── DataChangeBase.java
│ │ │ │ └── DataSaverBase.java
│ │ │ ├── proxy/
│ │ │ │ ├── PasswdInetSocketAddress.java
│ │ │ │ ├── PasswdURI.java
│ │ │ │ ├── Proxy.java
│ │ │ │ ├── ProxyManager.java
│ │ │ │ └── WebProxyDialog.java
│ │ │ └── utils/
│ │ │ ├── AppDialogUtil.java
│ │ │ ├── ClickbaitRemover.java
│ │ │ ├── CopyOnWriteHashList.java
│ │ │ ├── HttpURLConnectionUtils.java
│ │ │ ├── IntentExtractor.java
│ │ │ ├── LoadingManager.java
│ │ │ ├── SimpleEditDialog.java
│ │ │ ├── TvQuickActions.java
│ │ │ ├── UserAgentManager.java
│ │ │ └── Utils.java
│ │ └── res/
│ │ ├── layout/
│ │ │ ├── debug_view.xml
│ │ │ ├── dim_container.xml
│ │ │ ├── simple_edit_dialog.xml
│ │ │ └── web_proxy_dialog.xml
│ │ ├── values/
│ │ │ ├── colors.xml
│ │ │ ├── countries.xml
│ │ │ ├── dimens.xml
│ │ │ ├── donations.xml
│ │ │ ├── feedback.xml
│ │ │ ├── ids.xml
│ │ │ ├── languages.xml
│ │ │ ├── strings.xml
│ │ │ ├── styles.xml
│ │ │ ├── unlocalized-strings.xml
│ │ │ └── update_urls.xml
│ │ ├── values-ar/
│ │ │ └── strings.xml
│ │ ├── values-az/
│ │ │ └── strings.xml
│ │ ├── values-bg/
│ │ │ └── strings.xml
│ │ ├── values-ca/
│ │ │ └── strings.xml
│ │ ├── values-cs/
│ │ │ └── strings.xml
│ │ ├── values-da/
│ │ │ └── strings.xml
│ │ ├── values-de/
│ │ │ └── strings.xml
│ │ ├── values-el/
│ │ │ └── strings.xml
│ │ ├── values-es/
│ │ │ └── strings.xml
│ │ ├── values-et/
│ │ │ └── strings.xml
│ │ ├── values-fa-rIR/
│ │ │ └── strings.xml
│ │ ├── values-fi/
│ │ │ └── strings.xml
│ │ ├── values-fr/
│ │ │ └── strings.xml
│ │ ├── values-gl-rES/
│ │ │ └── strings.xml
│ │ ├── values-he/
│ │ │ └── strings.xml
│ │ ├── values-hi/
│ │ │ └── strings.xml
│ │ ├── values-hr/
│ │ │ └── strings.xml
│ │ ├── values-hu/
│ │ │ └── strings.xml
│ │ ├── values-hy/
│ │ │ └── strings.xml
│ │ ├── values-in/
│ │ │ └── strings.xml
│ │ ├── values-it/
│ │ │ └── strings.xml
│ │ ├── values-iw/
│ │ │ └── strings.xml
│ │ ├── values-ja/
│ │ │ └── strings.xml
│ │ ├── values-ko/
│ │ │ └── strings.xml
│ │ ├── values-lt/
│ │ │ └── strings.xml
│ │ ├── values-lv/
│ │ │ └── strings.xml
│ │ ├── values-mo/
│ │ │ └── strings.xml
│ │ ├── values-nb/
│ │ │ └── strings.xml
│ │ ├── values-nl/
│ │ │ └── strings.xml
│ │ ├── values-pl/
│ │ │ └── strings.xml
│ │ ├── values-pt-rBR/
│ │ │ └── strings.xml
│ │ ├── values-pt-rPT/
│ │ │ └── strings.xml
│ │ ├── values-ro/
│ │ │ └── strings.xml
│ │ ├── values-ru/
│ │ │ └── strings.xml
│ │ ├── values-sk/
│ │ │ └── strings.xml
│ │ ├── values-sl/
│ │ │ └── strings.xml
│ │ ├── values-sq/
│ │ │ └── strings.xml
│ │ ├── values-sr/
│ │ │ └── strings.xml
│ │ ├── values-sv/
│ │ │ └── strings.xml
│ │ ├── values-te/
│ │ │ └── strings.xml
│ │ ├── values-th/
│ │ │ └── strings.xml
│ │ ├── values-tr/
│ │ │ └── strings.xml
│ │ ├── values-uk/
│ │ │ └── strings.xml
│ │ ├── values-vi/
│ │ │ └── strings.xml
│ │ ├── values-zh/
│ │ │ └── strings.xml
│ │ ├── values-zh-rTW/
│ │ │ └── strings.xml
│ │ ├── volume-fa/
│ │ │ └── strings.xml
│ │ └── xml/
│ │ └── app_prefs.xml
│ ├── stbeta/
│ │ └── res/
│ │ └── values/
│ │ └── update_urls.xml
│ └── ststable/
│ └── res/
│ └── values/
│ └── update_urls.xml
├── crowdin.yml
├── doubletapplayerview/
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── build.gradle
│ ├── consumer-rules.pro
│ ├── proguard-rules.pro
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── com/
│ │ └── github/
│ │ └── vkay94/
│ │ └── dtpv/
│ │ ├── DoubleTapPlayerAdapter.kt
│ │ ├── DoubleTapPlayerView.kt
│ │ ├── DoubleTapPlayerViewImpl.kt
│ │ ├── PlayerDoubleTapListener.java
│ │ ├── SeekListener.kt
│ │ └── youtube/
│ │ ├── YouTubeOverlay.kt
│ │ └── views/
│ │ ├── CircleClipTapView.kt
│ │ └── YouTubeSecondsView.kt
│ └── res/
│ ├── drawable/
│ │ └── ic_play_triangle.xml
│ ├── layout/
│ │ ├── yt_overlay.xml
│ │ └── yt_seconds_view.xml
│ ├── values/
│ │ ├── dtpv.xml
│ │ ├── plurals.xml
│ │ ├── public.xml
│ │ └── yt_overlay.xml
│ ├── values-af/
│ │ └── plurals.xml
│ ├── values-am/
│ │ └── plurals.xml
│ ├── values-ar/
│ │ └── plurals.xml
│ ├── values-az/
│ │ └── plurals.xml
│ ├── values-b+sr+Latn/
│ │ └── plurals.xml
│ ├── values-be/
│ │ └── plurals.xml
│ ├── values-bg/
│ │ └── plurals.xml
│ ├── values-bn/
│ │ └── plurals.xml
│ ├── values-bs/
│ │ └── plurals.xml
│ ├── values-ca/
│ │ └── plurals.xml
│ ├── values-cs/
│ │ └── plurals.xml
│ ├── values-da/
│ │ └── plurals.xml
│ ├── values-de/
│ │ └── plurals.xml
│ ├── values-el/
│ │ └── plurals.xml
│ ├── values-en-rGB/
│ │ └── plurals.xml
│ ├── values-en-rIN/
│ │ └── plurals.xml
│ ├── values-es/
│ │ └── plurals.xml
│ ├── values-es-rUS/
│ │ └── plurals.xml
│ ├── values-et/
│ │ └── plurals.xml
│ ├── values-eu/
│ │ └── plurals.xml
│ ├── values-fa/
│ │ └── plurals.xml
│ ├── values-fi/
│ │ └── plurals.xml
│ ├── values-fr/
│ │ └── plurals.xml
│ ├── values-fr-rCA/
│ │ └── plurals.xml
│ ├── values-gl/
│ │ └── plurals.xml
│ ├── values-gu/
│ │ └── plurals.xml
│ ├── values-hi/
│ │ └── plurals.xml
│ ├── values-hr/
│ │ └── plurals.xml
│ ├── values-hu/
│ │ └── plurals.xml
│ ├── values-hy/
│ │ └── plurals.xml
│ ├── values-in/
│ │ └── plurals.xml
│ ├── values-is/
│ │ └── plurals.xml
│ ├── values-it/
│ │ └── plurals.xml
│ ├── values-iw/
│ │ └── plurals.xml
│ ├── values-ja/
│ │ └── plurals.xml
│ ├── values-ka/
│ │ └── plurals.xml
│ ├── values-kk/
│ │ └── plurals.xml
│ ├── values-km/
│ │ └── plurals.xml
│ ├── values-kn/
│ │ └── plurals.xml
│ ├── values-ko/
│ │ └── plurals.xml
│ ├── values-ky/
│ │ └── plurals.xml
│ ├── values-lo/
│ │ └── plurals.xml
│ ├── values-lt/
│ │ └── plurals.xml
│ ├── values-lv/
│ │ └── plurals.xml
│ ├── values-mk/
│ │ └── plurals.xml
│ ├── values-ml/
│ │ └── plurals.xml
│ ├── values-mn/
│ │ └── plurals.xml
│ ├── values-mr/
│ │ └── plurals.xml
│ ├── values-ms/
│ │ └── plurals.xml
│ ├── values-my/
│ │ └── plurals.xml
│ ├── values-nb/
│ │ └── plurals.xml
│ ├── values-ne/
│ │ └── plurals.xml
│ ├── values-nl/
│ │ └── plurals.xml
│ ├── values-pa/
│ │ └── plurals.xml
│ ├── values-pl/
│ │ └── plurals.xml
│ ├── values-pt-rBR/
│ │ └── plurals.xml
│ ├── values-pt-rPT/
│ │ └── plurals.xml
│ ├── values-ro/
│ │ └── plurals.xml
│ ├── values-ru/
│ │ └── plurals.xml
│ ├── values-si/
│ │ └── plurals.xml
│ ├── values-sk/
│ │ └── plurals.xml
│ ├── values-sl/
│ │ └── plurals.xml
│ ├── values-sq/
│ │ └── plurals.xml
│ ├── values-sr/
│ │ └── plurals.xml
│ ├── values-sv/
│ │ └── plurals.xml
│ ├── values-sw/
│ │ └── plurals.xml
│ ├── values-ta/
│ │ └── plurals.xml
│ ├── values-te/
│ │ └── plurals.xml
│ ├── values-th/
│ │ └── plurals.xml
│ ├── values-tl/
│ │ └── plurals.xml
│ ├── values-tr/
│ │ └── plurals.xml
│ ├── values-uk/
│ │ └── plurals.xml
│ ├── values-ur/
│ │ └── plurals.xml
│ ├── values-uz/
│ │ └── plurals.xml
│ ├── values-vi/
│ │ └── plurals.xml
│ ├── values-zh-rCN/
│ │ └── plurals.xml
│ ├── values-zh-rHK/
│ │ └── plurals.xml
│ ├── values-zh-rTW/
│ │ └── plurals.xml
│ └── values-zu/
│ └── plurals.xml
├── exoplayer-amzn-2.10.6/
│ ├── .gitignore
│ ├── .hgignore
│ ├── CONTRIBUTING.md
│ ├── LICENSE
│ ├── README-ORIGINAL.md
│ ├── README.md
│ ├── RELEASENOTES.md
│ ├── build.gradle
│ ├── constants.gradle
│ ├── core_settings.gradle
│ ├── demos/
│ │ ├── README.md
│ │ ├── cast/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ ├── proguard-rules.txt
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── castdemo/
│ │ │ │ ├── DefaultReceiverPlayerManager.java
│ │ │ │ ├── DemoUtil.java
│ │ │ │ ├── MainActivity.java
│ │ │ │ └── PlayerManager.java
│ │ │ └── res/
│ │ │ ├── drawable/
│ │ │ │ └── ic_plus.xml
│ │ │ ├── layout/
│ │ │ │ ├── cast_context_error.xml
│ │ │ │ ├── main_activity.xml
│ │ │ │ └── sample_list.xml
│ │ │ ├── menu/
│ │ │ │ └── menu.xml
│ │ │ └── values/
│ │ │ └── strings.xml
│ │ ├── ima/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── imademo/
│ │ │ │ ├── MainActivity.java
│ │ │ │ └── PlayerManager.java
│ │ │ └── res/
│ │ │ ├── layout/
│ │ │ │ └── main_activity.xml
│ │ │ └── values/
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ └── main/
│ │ ├── README.md
│ │ ├── build.gradle
│ │ ├── proguard-rules.txt
│ │ └── src/
│ │ └── main/
│ │ ├── AndroidManifest.xml
│ │ ├── assets/
│ │ │ └── media.exolist.json
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── demo/
│ │ │ ├── DemoApplication.java
│ │ │ ├── DemoDownloadService.java
│ │ │ ├── DownloadTracker.java
│ │ │ ├── PlayerActivity.java
│ │ │ ├── SampleChooserActivity.java
│ │ │ └── TrackSelectionDialog.java
│ │ └── res/
│ │ ├── layout/
│ │ │ ├── player_activity.xml
│ │ │ ├── sample_chooser_activity.xml
│ │ │ ├── sample_list_item.xml
│ │ │ └── track_selection_dialog.xml
│ │ ├── menu/
│ │ │ └── sample_chooser_menu.xml
│ │ └── values/
│ │ ├── strings.xml
│ │ └── styles.xml
│ ├── extensions/
│ │ ├── README.md
│ │ ├── cast/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── ext/
│ │ │ │ └── cast/
│ │ │ │ ├── CastPlayer.java
│ │ │ │ ├── CastTimeline.java
│ │ │ │ ├── CastTimelineTracker.java
│ │ │ │ ├── CastUtils.java
│ │ │ │ ├── DefaultCastOptionsProvider.java
│ │ │ │ ├── MediaItem.java
│ │ │ │ ├── MediaItemQueue.java
│ │ │ │ └── SessionAvailabilityListener.java
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── cast/
│ │ │ ├── CastTimelineTrackerTest.java
│ │ │ └── MediaItemTest.java
│ │ ├── cronet/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── ext/
│ │ │ │ └── cronet/
│ │ │ │ ├── ByteArrayUploadDataProvider.java
│ │ │ │ ├── CronetDataSource.java
│ │ │ │ ├── CronetDataSourceFactory.java
│ │ │ │ └── CronetEngineWrapper.java
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── cronet/
│ │ │ ├── ByteArrayUploadDataProviderTest.java
│ │ │ └── CronetDataSourceTest.java
│ │ ├── ffmpeg/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ ├── proguard-rules.txt
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── java/
│ │ │ │ │ └── com/
│ │ │ │ │ └── google/
│ │ │ │ │ └── android/
│ │ │ │ │ └── exoplayer2/
│ │ │ │ │ └── ext/
│ │ │ │ │ └── ffmpeg/
│ │ │ │ │ ├── FfmpegAudioRenderer.java
│ │ │ │ │ ├── FfmpegDecoder.java
│ │ │ │ │ ├── FfmpegDecoderException.java
│ │ │ │ │ └── FfmpegLibrary.java
│ │ │ │ └── jni/
│ │ │ │ ├── Android.mk
│ │ │ │ ├── Application.mk
│ │ │ │ └── ffmpeg_jni.cc
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── ffmpeg/
│ │ │ └── DefaultRenderersFactoryTest.java
│ │ ├── flac/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ ├── proguard-rules.txt
│ │ │ └── src/
│ │ │ ├── androidTest/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── assets/
│ │ │ │ │ ├── bear-flac.mka
│ │ │ │ │ ├── bear.flac
│ │ │ │ │ ├── bear.flac.0.dump
│ │ │ │ │ ├── bear.flac.1.dump
│ │ │ │ │ ├── bear.flac.2.dump
│ │ │ │ │ ├── bear.flac.3.dump
│ │ │ │ │ ├── bear_no_seek.flac
│ │ │ │ │ ├── bear_with_id3.flac
│ │ │ │ │ ├── bear_with_id3.flac.0.dump
│ │ │ │ │ ├── bear_with_id3.flac.1.dump
│ │ │ │ │ ├── bear_with_id3.flac.2.dump
│ │ │ │ │ └── bear_with_id3.flac.3.dump
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── ext/
│ │ │ │ └── flac/
│ │ │ │ ├── FlacBinarySearchSeekerTest.java
│ │ │ │ ├── FlacExtractorSeekTest.java
│ │ │ │ ├── FlacExtractorTest.java
│ │ │ │ └── FlacPlaybackTest.java
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── java/
│ │ │ │ │ └── com/
│ │ │ │ │ └── google/
│ │ │ │ │ └── android/
│ │ │ │ │ └── exoplayer2/
│ │ │ │ │ └── ext/
│ │ │ │ │ └── flac/
│ │ │ │ │ ├── FlacBinarySearchSeeker.java
│ │ │ │ │ ├── FlacDecoder.java
│ │ │ │ │ ├── FlacDecoderException.java
│ │ │ │ │ ├── FlacDecoderJni.java
│ │ │ │ │ ├── FlacExtractor.java
│ │ │ │ │ ├── FlacLibrary.java
│ │ │ │ │ └── LibflacAudioRenderer.java
│ │ │ │ └── jni/
│ │ │ │ ├── Android.mk
│ │ │ │ ├── Application.mk
│ │ │ │ ├── flac_jni.cc
│ │ │ │ ├── flac_parser.cc
│ │ │ │ ├── flac_sources.mk
│ │ │ │ └── include/
│ │ │ │ ├── data_source.h
│ │ │ │ └── flac_parser.h
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── flac/
│ │ │ ├── DefaultExtractorsFactoryTest.java
│ │ │ └── DefaultRenderersFactoryTest.java
│ │ ├── gvr/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── ext/
│ │ │ │ └── gvr/
│ │ │ │ ├── GvrAudioProcessor.java
│ │ │ │ └── GvrPlayerActivity.java
│ │ │ └── res/
│ │ │ ├── layout/
│ │ │ │ └── vr_ui.xml
│ │ │ ├── values/
│ │ │ │ └── styles.xml
│ │ │ └── values-v21/
│ │ │ └── styles.xml
│ │ ├── ima/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ ├── proguard-rules.txt
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── ext/
│ │ │ │ └── ima/
│ │ │ │ └── ImaAdsLoader.java
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── ima/
│ │ │ ├── FakeAd.java
│ │ │ ├── FakeAdsLoader.java
│ │ │ ├── FakeAdsRequest.java
│ │ │ ├── FakePlayer.java
│ │ │ ├── ImaAdsLoaderTest.java
│ │ │ └── SingletonImaFactory.java
│ │ ├── jobdispatcher/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── jobdispatcher/
│ │ │ └── JobDispatcherScheduler.java
│ │ ├── leanback/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── leanback/
│ │ │ └── LeanbackPlayerAdapter.java
│ │ ├── mediasession/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── ext/
│ │ │ │ └── mediasession/
│ │ │ │ ├── MediaSessionConnector.java
│ │ │ │ ├── RepeatModeActionProvider.java
│ │ │ │ ├── TimelineQueueEditor.java
│ │ │ │ └── TimelineQueueNavigator.java
│ │ │ └── res/
│ │ │ ├── drawable-anydpi-v21/
│ │ │ │ ├── exo_media_action_repeat_all.xml
│ │ │ │ ├── exo_media_action_repeat_off.xml
│ │ │ │ └── exo_media_action_repeat_one.xml
│ │ │ ├── values/
│ │ │ │ └── strings.xml
│ │ │ ├── values-af/
│ │ │ │ └── strings.xml
│ │ │ ├── values-am/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ar/
│ │ │ │ └── strings.xml
│ │ │ ├── values-az/
│ │ │ │ └── strings.xml
│ │ │ ├── values-b+sr+Latn/
│ │ │ │ └── strings.xml
│ │ │ ├── values-be/
│ │ │ │ └── strings.xml
│ │ │ ├── values-bg/
│ │ │ │ └── strings.xml
│ │ │ ├── values-bn/
│ │ │ │ └── strings.xml
│ │ │ ├── values-bs/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ca/
│ │ │ │ └── strings.xml
│ │ │ ├── values-cs/
│ │ │ │ └── strings.xml
│ │ │ ├── values-da/
│ │ │ │ └── strings.xml
│ │ │ ├── values-de/
│ │ │ │ └── strings.xml
│ │ │ ├── values-el/
│ │ │ │ └── strings.xml
│ │ │ ├── values-en-rAU/
│ │ │ │ └── strings.xml
│ │ │ ├── values-en-rGB/
│ │ │ │ └── strings.xml
│ │ │ ├── values-en-rIN/
│ │ │ │ └── strings.xml
│ │ │ ├── values-es/
│ │ │ │ └── strings.xml
│ │ │ ├── values-es-rUS/
│ │ │ │ └── strings.xml
│ │ │ ├── values-et/
│ │ │ │ └── strings.xml
│ │ │ ├── values-eu/
│ │ │ │ └── strings.xml
│ │ │ ├── values-fa/
│ │ │ │ └── strings.xml
│ │ │ ├── values-fi/
│ │ │ │ └── strings.xml
│ │ │ ├── values-fr/
│ │ │ │ └── strings.xml
│ │ │ ├── values-fr-rCA/
│ │ │ │ └── strings.xml
│ │ │ ├── values-gl/
│ │ │ │ └── strings.xml
│ │ │ ├── values-gu/
│ │ │ │ └── strings.xml
│ │ │ ├── values-hi/
│ │ │ │ └── strings.xml
│ │ │ ├── values-hr/
│ │ │ │ └── strings.xml
│ │ │ ├── values-hu/
│ │ │ │ └── strings.xml
│ │ │ ├── values-hy/
│ │ │ │ └── strings.xml
│ │ │ ├── values-in/
│ │ │ │ └── strings.xml
│ │ │ ├── values-is/
│ │ │ │ └── strings.xml
│ │ │ ├── values-it/
│ │ │ │ └── strings.xml
│ │ │ ├── values-iw/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ja/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ka/
│ │ │ │ └── strings.xml
│ │ │ ├── values-kk/
│ │ │ │ └── strings.xml
│ │ │ ├── values-km/
│ │ │ │ └── strings.xml
│ │ │ ├── values-kn/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ko/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ky/
│ │ │ │ └── strings.xml
│ │ │ ├── values-lo/
│ │ │ │ └── strings.xml
│ │ │ ├── values-lt/
│ │ │ │ └── strings.xml
│ │ │ ├── values-lv/
│ │ │ │ └── strings.xml
│ │ │ ├── values-mk/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ml/
│ │ │ │ └── strings.xml
│ │ │ ├── values-mn/
│ │ │ │ └── strings.xml
│ │ │ ├── values-mr/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ms/
│ │ │ │ └── strings.xml
│ │ │ ├── values-my/
│ │ │ │ └── strings.xml
│ │ │ ├── values-nb/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ne/
│ │ │ │ └── strings.xml
│ │ │ ├── values-nl/
│ │ │ │ └── strings.xml
│ │ │ ├── values-pa/
│ │ │ │ └── strings.xml
│ │ │ ├── values-pl/
│ │ │ │ └── strings.xml
│ │ │ ├── values-pt/
│ │ │ │ └── strings.xml
│ │ │ ├── values-pt-rPT/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ro/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ru/
│ │ │ │ └── strings.xml
│ │ │ ├── values-si/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sk/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sl/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sq/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sr/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sv/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sw/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ta/
│ │ │ │ └── strings.xml
│ │ │ ├── values-te/
│ │ │ │ └── strings.xml
│ │ │ ├── values-th/
│ │ │ │ └── strings.xml
│ │ │ ├── values-tl/
│ │ │ │ └── strings.xml
│ │ │ ├── values-tr/
│ │ │ │ └── strings.xml
│ │ │ ├── values-uk/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ur/
│ │ │ │ └── strings.xml
│ │ │ ├── values-uz/
│ │ │ │ └── strings.xml
│ │ │ ├── values-vi/
│ │ │ │ └── strings.xml
│ │ │ ├── values-zh-rCN/
│ │ │ │ └── strings.xml
│ │ │ ├── values-zh-rHK/
│ │ │ │ └── strings.xml
│ │ │ ├── values-zh-rTW/
│ │ │ │ └── strings.xml
│ │ │ └── values-zu/
│ │ │ └── strings.xml
│ │ ├── okhttp/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ ├── proguard-rules.txt
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── okhttp/
│ │ │ ├── OkHttpDataSource.java
│ │ │ └── OkHttpDataSourceFactory.java
│ │ ├── opus/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ ├── proguard-rules.txt
│ │ │ └── src/
│ │ │ ├── androidTest/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── assets/
│ │ │ │ │ └── bear-opus.webm
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── ext/
│ │ │ │ └── opus/
│ │ │ │ └── OpusPlaybackTest.java
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── java/
│ │ │ │ │ └── com/
│ │ │ │ │ └── google/
│ │ │ │ │ └── android/
│ │ │ │ │ └── exoplayer2/
│ │ │ │ │ └── ext/
│ │ │ │ │ └── opus/
│ │ │ │ │ ├── LibopusAudioRenderer.java
│ │ │ │ │ ├── OpusDecoder.java
│ │ │ │ │ ├── OpusDecoderException.java
│ │ │ │ │ └── OpusLibrary.java
│ │ │ │ └── jni/
│ │ │ │ ├── Android.mk
│ │ │ │ ├── Application.mk
│ │ │ │ ├── convert_android_asm.sh
│ │ │ │ ├── libopus.mk
│ │ │ │ └── opus_jni.cc
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── opus/
│ │ │ └── DefaultRenderersFactoryTest.java
│ │ ├── rtmp/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── ext/
│ │ │ │ └── rtmp/
│ │ │ │ ├── RtmpDataSource.java
│ │ │ │ └── RtmpDataSourceFactory.java
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── rtmp/
│ │ │ └── DefaultDataSourceTest.java
│ │ ├── vp9/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ ├── proguard-rules.txt
│ │ │ └── src/
│ │ │ ├── androidTest/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── assets/
│ │ │ │ │ ├── bear-vp9-odd-dimensions.webm
│ │ │ │ │ ├── bear-vp9.webm
│ │ │ │ │ ├── invalid-bitstream.webm
│ │ │ │ │ └── roadtrip-vp92-10bit.webm
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── ext/
│ │ │ │ └── vp9/
│ │ │ │ └── VpxPlaybackTest.java
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── java/
│ │ │ │ │ └── com/
│ │ │ │ │ └── google/
│ │ │ │ │ └── android/
│ │ │ │ │ └── exoplayer2/
│ │ │ │ │ └── ext/
│ │ │ │ │ └── vp9/
│ │ │ │ │ ├── LibvpxVideoRenderer.java
│ │ │ │ │ ├── VpxDecoder.java
│ │ │ │ │ ├── VpxDecoderException.java
│ │ │ │ │ ├── VpxInputBuffer.java
│ │ │ │ │ ├── VpxLibrary.java
│ │ │ │ │ ├── VpxOutputBuffer.java
│ │ │ │ │ ├── VpxOutputBufferRenderer.java
│ │ │ │ │ ├── VpxRenderer.java
│ │ │ │ │ └── VpxVideoSurfaceView.java
│ │ │ │ └── jni/
│ │ │ │ ├── Android.mk
│ │ │ │ ├── Application.mk
│ │ │ │ ├── generate_libvpx_android_configs.sh
│ │ │ │ ├── libvpx.mk
│ │ │ │ └── vpx_jni.cc
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── ext/
│ │ │ └── vp9/
│ │ │ └── DefaultRenderersFactoryTest.java
│ │ └── workmanager/
│ │ ├── README.md
│ │ ├── build.gradle
│ │ └── src/
│ │ └── main/
│ │ ├── AndroidManifest.xml
│ │ └── java/
│ │ └── com/
│ │ └── google/
│ │ └── android/
│ │ └── exoplayer2/
│ │ └── ext/
│ │ └── workmanager/
│ │ └── WorkManagerScheduler.java
│ ├── gradle/
│ │ └── wrapper/
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
│ ├── gradle.properties
│ ├── gradlew
│ ├── gradlew.bat
│ ├── issues/
│ │ └── player-accessed-on-wrong-thread.md
│ ├── javadoc_combined.gradle
│ ├── javadoc_library.gradle
│ ├── javadoc_util.gradle
│ ├── library/
│ │ ├── README.md
│ │ ├── all/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ └── main/
│ │ │ └── AndroidManifest.xml
│ │ ├── core/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ ├── proguard-rules.txt
│ │ │ └── src/
│ │ │ ├── androidTest/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── upstream/
│ │ │ │ └── ContentDataSourceTest.java
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ ├── BasePlayer.java
│ │ │ │ ├── BaseRenderer.java
│ │ │ │ ├── C.java
│ │ │ │ ├── ControlDispatcher.java
│ │ │ │ ├── DefaultControlDispatcher.java
│ │ │ │ ├── DefaultLoadControl.java
│ │ │ │ ├── DefaultMediaClock.java
│ │ │ │ ├── DefaultRenderersFactory.java
│ │ │ │ ├── ExoPlaybackException.java
│ │ │ │ ├── ExoPlayer.java
│ │ │ │ ├── ExoPlayerFactory.java
│ │ │ │ ├── ExoPlayerImpl.java
│ │ │ │ ├── ExoPlayerImplInternal.java
│ │ │ │ ├── ExoPlayerLibraryInfo.java
│ │ │ │ ├── Format.java
│ │ │ │ ├── FormatHolder.java
│ │ │ │ ├── IllegalSeekPositionException.java
│ │ │ │ ├── LoadControl.java
│ │ │ │ ├── MediaPeriodHolder.java
│ │ │ │ ├── MediaPeriodInfo.java
│ │ │ │ ├── MediaPeriodQueue.java
│ │ │ │ ├── NoSampleRenderer.java
│ │ │ │ ├── ParserException.java
│ │ │ │ ├── PlaybackInfo.java
│ │ │ │ ├── PlaybackParameters.java
│ │ │ │ ├── PlaybackPreparer.java
│ │ │ │ ├── Player.java
│ │ │ │ ├── PlayerMessage.java
│ │ │ │ ├── Renderer.java
│ │ │ │ ├── RendererCapabilities.java
│ │ │ │ ├── RendererConfiguration.java
│ │ │ │ ├── RenderersFactory.java
│ │ │ │ ├── SeekParameters.java
│ │ │ │ ├── SimpleExoPlayer.java
│ │ │ │ ├── Timeline.java
│ │ │ │ ├── analytics/
│ │ │ │ │ ├── AnalyticsCollector.java
│ │ │ │ │ ├── AnalyticsListener.java
│ │ │ │ │ └── DefaultAnalyticsListener.java
│ │ │ │ ├── audio/
│ │ │ │ │ ├── Ac3Util.java
│ │ │ │ │ ├── Ac4Util.java
│ │ │ │ │ ├── AudioAttributes.java
│ │ │ │ │ ├── AudioCapabilities.java
│ │ │ │ │ ├── AudioCapabilitiesReceiver.java
│ │ │ │ │ ├── AudioDecoderException.java
│ │ │ │ │ ├── AudioFocusManager.java
│ │ │ │ │ ├── AudioListener.java
│ │ │ │ │ ├── AudioProcessor.java
│ │ │ │ │ ├── AudioRendererEventListener.java
│ │ │ │ │ ├── AudioSink.java
│ │ │ │ │ ├── AudioTimestampPoller.java
│ │ │ │ │ ├── AudioTrackPositionTracker.java
│ │ │ │ │ ├── AuxEffectInfo.java
│ │ │ │ │ ├── BaseAudioProcessor.java
│ │ │ │ │ ├── ChannelMappingAudioProcessor.java
│ │ │ │ │ ├── DefaultAudioSink.java
│ │ │ │ │ ├── DolbyPassthroughAudioTrack.java
│ │ │ │ │ ├── DtsUtil.java
│ │ │ │ │ ├── FloatResamplingAudioProcessor.java
│ │ │ │ │ ├── MediaCodecAudioRenderer.java
│ │ │ │ │ ├── ResamplingAudioProcessor.java
│ │ │ │ │ ├── SilenceSkippingAudioProcessor.java
│ │ │ │ │ ├── SimpleDecoderAudioRenderer.java
│ │ │ │ │ ├── Sonic.java
│ │ │ │ │ ├── SonicAudioProcessor.java
│ │ │ │ │ ├── TeeAudioProcessor.java
│ │ │ │ │ ├── TrimmingAudioProcessor.java
│ │ │ │ │ └── WavUtil.java
│ │ │ │ ├── database/
│ │ │ │ │ ├── DatabaseIOException.java
│ │ │ │ │ ├── DatabaseProvider.java
│ │ │ │ │ ├── DefaultDatabaseProvider.java
│ │ │ │ │ ├── ExoDatabaseProvider.java
│ │ │ │ │ └── VersionTable.java
│ │ │ │ ├── decoder/
│ │ │ │ │ ├── Buffer.java
│ │ │ │ │ ├── CryptoInfo.java
│ │ │ │ │ ├── Decoder.java
│ │ │ │ │ ├── DecoderCounters.java
│ │ │ │ │ ├── DecoderInputBuffer.java
│ │ │ │ │ ├── OutputBuffer.java
│ │ │ │ │ ├── SimpleDecoder.java
│ │ │ │ │ └── SimpleOutputBuffer.java
│ │ │ │ ├── drm/
│ │ │ │ │ ├── ClearKeyUtil.java
│ │ │ │ │ ├── DecryptionException.java
│ │ │ │ │ ├── DecryptionResource.java
│ │ │ │ │ ├── DefaultDrmSession.java
│ │ │ │ │ ├── DefaultDrmSessionEventListener.java
│ │ │ │ │ ├── DefaultDrmSessionManager.java
│ │ │ │ │ ├── DrmInitData.java
│ │ │ │ │ ├── DrmSession.java
│ │ │ │ │ ├── DrmSessionManager.java
│ │ │ │ │ ├── ErrorStateDrmSession.java
│ │ │ │ │ ├── ExoMediaCrypto.java
│ │ │ │ │ ├── ExoMediaDrm.java
│ │ │ │ │ ├── FrameworkMediaCrypto.java
│ │ │ │ │ ├── FrameworkMediaDrm.java
│ │ │ │ │ ├── HttpMediaDrmCallback.java
│ │ │ │ │ ├── KeysExpiredException.java
│ │ │ │ │ ├── LocalMediaDrmCallback.java
│ │ │ │ │ ├── MediaDrmCallback.java
│ │ │ │ │ ├── OfflineLicenseHelper.java
│ │ │ │ │ ├── UnsupportedDrmException.java
│ │ │ │ │ └── WidevineUtil.java
│ │ │ │ ├── extractor/
│ │ │ │ │ ├── BinarySearchSeeker.java
│ │ │ │ │ ├── ChunkIndex.java
│ │ │ │ │ ├── ConstantBitrateSeekMap.java
│ │ │ │ │ ├── DefaultExtractorInput.java
│ │ │ │ │ ├── DefaultExtractorsFactory.java
│ │ │ │ │ ├── DummyExtractorOutput.java
│ │ │ │ │ ├── DummyTrackOutput.java
│ │ │ │ │ ├── Extractor.java
│ │ │ │ │ ├── ExtractorInput.java
│ │ │ │ │ ├── ExtractorOutput.java
│ │ │ │ │ ├── ExtractorsFactory.java
│ │ │ │ │ ├── GaplessInfoHolder.java
│ │ │ │ │ ├── Id3Peeker.java
│ │ │ │ │ ├── MpegAudioHeader.java
│ │ │ │ │ ├── PositionHolder.java
│ │ │ │ │ ├── SeekMap.java
│ │ │ │ │ ├── SeekPoint.java
│ │ │ │ │ ├── TrackOutput.java
│ │ │ │ │ ├── amr/
│ │ │ │ │ │ └── AmrExtractor.java
│ │ │ │ │ ├── flv/
│ │ │ │ │ │ ├── AudioTagPayloadReader.java
│ │ │ │ │ │ ├── FlvExtractor.java
│ │ │ │ │ │ ├── ScriptTagPayloadReader.java
│ │ │ │ │ │ ├── TagPayloadReader.java
│ │ │ │ │ │ └── VideoTagPayloadReader.java
│ │ │ │ │ ├── mkv/
│ │ │ │ │ │ ├── DefaultEbmlReader.java
│ │ │ │ │ │ ├── EbmlProcessor.java
│ │ │ │ │ │ ├── EbmlReader.java
│ │ │ │ │ │ ├── MatroskaExtractor.java
│ │ │ │ │ │ ├── Sniffer.java
│ │ │ │ │ │ └── VarintReader.java
│ │ │ │ │ ├── mp3/
│ │ │ │ │ │ ├── ConstantBitrateSeeker.java
│ │ │ │ │ │ ├── MlltSeeker.java
│ │ │ │ │ │ ├── Mp3Extractor.java
│ │ │ │ │ │ ├── Seeker.java
│ │ │ │ │ │ ├── VbriSeeker.java
│ │ │ │ │ │ └── XingSeeker.java
│ │ │ │ │ ├── mp4/
│ │ │ │ │ │ ├── Atom.java
│ │ │ │ │ │ ├── AtomParsers.java
│ │ │ │ │ │ ├── DefaultSampleValues.java
│ │ │ │ │ │ ├── FixedSampleSizeRechunker.java
│ │ │ │ │ │ ├── FragmentedMp4Extractor.java
│ │ │ │ │ │ ├── MdtaMetadataEntry.java
│ │ │ │ │ │ ├── MetadataUtil.java
│ │ │ │ │ │ ├── Mp4Extractor.java
│ │ │ │ │ │ ├── PsshAtomUtil.java
│ │ │ │ │ │ ├── Sniffer.java
│ │ │ │ │ │ ├── Track.java
│ │ │ │ │ │ ├── TrackEncryptionBox.java
│ │ │ │ │ │ ├── TrackFragment.java
│ │ │ │ │ │ └── TrackSampleTable.java
│ │ │ │ │ ├── ogg/
│ │ │ │ │ │ ├── DefaultOggSeeker.java
│ │ │ │ │ │ ├── FlacReader.java
│ │ │ │ │ │ ├── OggExtractor.java
│ │ │ │ │ │ ├── OggPacket.java
│ │ │ │ │ │ ├── OggPageHeader.java
│ │ │ │ │ │ ├── OggSeeker.java
│ │ │ │ │ │ ├── OpusReader.java
│ │ │ │ │ │ ├── StreamReader.java
│ │ │ │ │ │ ├── VorbisBitArray.java
│ │ │ │ │ │ ├── VorbisReader.java
│ │ │ │ │ │ └── VorbisUtil.java
│ │ │ │ │ ├── rawcc/
│ │ │ │ │ │ └── RawCcExtractor.java
│ │ │ │ │ ├── ts/
│ │ │ │ │ │ ├── Ac3Extractor.java
│ │ │ │ │ │ ├── Ac3Reader.java
│ │ │ │ │ │ ├── Ac4Extractor.java
│ │ │ │ │ │ ├── Ac4Reader.java
│ │ │ │ │ │ ├── AdtsExtractor.java
│ │ │ │ │ │ ├── AdtsReader.java
│ │ │ │ │ │ ├── DefaultTsPayloadReaderFactory.java
│ │ │ │ │ │ ├── DtsReader.java
│ │ │ │ │ │ ├── DvbSubtitleReader.java
│ │ │ │ │ │ ├── ElementaryStreamReader.java
│ │ │ │ │ │ ├── H262Reader.java
│ │ │ │ │ │ ├── H264Reader.java
│ │ │ │ │ │ ├── H265Reader.java
│ │ │ │ │ │ ├── Id3Reader.java
│ │ │ │ │ │ ├── LatmReader.java
│ │ │ │ │ │ ├── MpegAudioReader.java
│ │ │ │ │ │ ├── NalUnitTargetBuffer.java
│ │ │ │ │ │ ├── PesReader.java
│ │ │ │ │ │ ├── PsBinarySearchSeeker.java
│ │ │ │ │ │ ├── PsDurationReader.java
│ │ │ │ │ │ ├── PsExtractor.java
│ │ │ │ │ │ ├── SectionPayloadReader.java
│ │ │ │ │ │ ├── SectionReader.java
│ │ │ │ │ │ ├── SeiReader.java
│ │ │ │ │ │ ├── SpliceInfoSectionReader.java
│ │ │ │ │ │ ├── TsBinarySearchSeeker.java
│ │ │ │ │ │ ├── TsDurationReader.java
│ │ │ │ │ │ ├── TsExtractor.java
│ │ │ │ │ │ ├── TsPayloadReader.java
│ │ │ │ │ │ ├── TsUtil.java
│ │ │ │ │ │ └── UserDataReader.java
│ │ │ │ │ └── wav/
│ │ │ │ │ ├── WavExtractor.java
│ │ │ │ │ ├── WavHeader.java
│ │ │ │ │ └── WavHeaderReader.java
│ │ │ │ ├── mediacodec/
│ │ │ │ │ ├── MediaCodecInfo.java
│ │ │ │ │ ├── MediaCodecRenderer.java
│ │ │ │ │ ├── MediaCodecSelector.java
│ │ │ │ │ ├── MediaCodecUtil.java
│ │ │ │ │ └── MediaFormatUtil.java
│ │ │ │ ├── metadata/
│ │ │ │ │ ├── Metadata.java
│ │ │ │ │ ├── MetadataDecoder.java
│ │ │ │ │ ├── MetadataDecoderFactory.java
│ │ │ │ │ ├── MetadataInputBuffer.java
│ │ │ │ │ ├── MetadataOutput.java
│ │ │ │ │ ├── MetadataRenderer.java
│ │ │ │ │ ├── emsg/
│ │ │ │ │ │ ├── EventMessage.java
│ │ │ │ │ │ ├── EventMessageDecoder.java
│ │ │ │ │ │ └── EventMessageEncoder.java
│ │ │ │ │ ├── flac/
│ │ │ │ │ │ ├── PictureFrame.java
│ │ │ │ │ │ └── VorbisComment.java
│ │ │ │ │ ├── icy/
│ │ │ │ │ │ ├── IcyDecoder.java
│ │ │ │ │ │ ├── IcyHeaders.java
│ │ │ │ │ │ └── IcyInfo.java
│ │ │ │ │ ├── id3/
│ │ │ │ │ │ ├── ApicFrame.java
│ │ │ │ │ │ ├── BinaryFrame.java
│ │ │ │ │ │ ├── ChapterFrame.java
│ │ │ │ │ │ ├── ChapterTocFrame.java
│ │ │ │ │ │ ├── CommentFrame.java
│ │ │ │ │ │ ├── GeobFrame.java
│ │ │ │ │ │ ├── Id3Decoder.java
│ │ │ │ │ │ ├── Id3Frame.java
│ │ │ │ │ │ ├── InternalFrame.java
│ │ │ │ │ │ ├── MlltFrame.java
│ │ │ │ │ │ ├── PrivFrame.java
│ │ │ │ │ │ ├── TextInformationFrame.java
│ │ │ │ │ │ └── UrlLinkFrame.java
│ │ │ │ │ └── scte35/
│ │ │ │ │ ├── PrivateCommand.java
│ │ │ │ │ ├── SpliceCommand.java
│ │ │ │ │ ├── SpliceInfoDecoder.java
│ │ │ │ │ ├── SpliceInsertCommand.java
│ │ │ │ │ ├── SpliceNullCommand.java
│ │ │ │ │ ├── SpliceScheduleCommand.java
│ │ │ │ │ └── TimeSignalCommand.java
│ │ │ │ ├── offline/
│ │ │ │ │ ├── ActionFile.java
│ │ │ │ │ ├── ActionFileUpgradeUtil.java
│ │ │ │ │ ├── DefaultDownloadIndex.java
│ │ │ │ │ ├── DefaultDownloaderFactory.java
│ │ │ │ │ ├── Download.java
│ │ │ │ │ ├── DownloadCursor.java
│ │ │ │ │ ├── DownloadException.java
│ │ │ │ │ ├── DownloadHelper.java
│ │ │ │ │ ├── DownloadIndex.java
│ │ │ │ │ ├── DownloadManager.java
│ │ │ │ │ ├── DownloadProgress.java
│ │ │ │ │ ├── DownloadRequest.java
│ │ │ │ │ ├── DownloadService.java
│ │ │ │ │ ├── Downloader.java
│ │ │ │ │ ├── DownloaderConstructorHelper.java
│ │ │ │ │ ├── DownloaderFactory.java
│ │ │ │ │ ├── FilterableManifest.java
│ │ │ │ │ ├── FilteringManifestParser.java
│ │ │ │ │ ├── ProgressiveDownloader.java
│ │ │ │ │ ├── SegmentDownloader.java
│ │ │ │ │ ├── StreamKey.java
│ │ │ │ │ └── WritableDownloadIndex.java
│ │ │ │ ├── scheduler/
│ │ │ │ │ ├── PlatformScheduler.java
│ │ │ │ │ ├── Requirements.java
│ │ │ │ │ ├── RequirementsWatcher.java
│ │ │ │ │ └── Scheduler.java
│ │ │ │ ├── source/
│ │ │ │ │ ├── AbstractConcatenatedTimeline.java
│ │ │ │ │ ├── AdaptiveMediaSourceEventListener.java
│ │ │ │ │ ├── BaseMediaSource.java
│ │ │ │ │ ├── BehindLiveWindowException.java
│ │ │ │ │ ├── ClippingMediaPeriod.java
│ │ │ │ │ ├── ClippingMediaSource.java
│ │ │ │ │ ├── CompositeMediaSource.java
│ │ │ │ │ ├── CompositeSequenceableLoader.java
│ │ │ │ │ ├── CompositeSequenceableLoaderFactory.java
│ │ │ │ │ ├── ConcatenatingMediaSource.java
│ │ │ │ │ ├── DefaultCompositeSequenceableLoaderFactory.java
│ │ │ │ │ ├── DefaultMediaSourceEventListener.java
│ │ │ │ │ ├── DeferredMediaPeriod.java
│ │ │ │ │ ├── DynamicConcatenatingMediaSource.java
│ │ │ │ │ ├── EmptySampleStream.java
│ │ │ │ │ ├── ExtractorMediaSource.java
│ │ │ │ │ ├── ForwardingTimeline.java
│ │ │ │ │ ├── IcyDataSource.java
│ │ │ │ │ ├── LoopingMediaSource.java
│ │ │ │ │ ├── MediaPeriod.java
│ │ │ │ │ ├── MediaSource.java
│ │ │ │ │ ├── MediaSourceEventListener.java
│ │ │ │ │ ├── MergingMediaPeriod.java
│ │ │ │ │ ├── MergingMediaSource.java
│ │ │ │ │ ├── ProgressiveMediaPeriod.java
│ │ │ │ │ ├── ProgressiveMediaSource.java
│ │ │ │ │ ├── SampleMetadataQueue.java
│ │ │ │ │ ├── SampleQueue.java
│ │ │ │ │ ├── SampleStream.java
│ │ │ │ │ ├── SequenceableLoader.java
│ │ │ │ │ ├── ShuffleOrder.java
│ │ │ │ │ ├── SilenceMediaSource.java
│ │ │ │ │ ├── SinglePeriodTimeline.java
│ │ │ │ │ ├── SingleSampleMediaPeriod.java
│ │ │ │ │ ├── SingleSampleMediaSource.java
│ │ │ │ │ ├── TrackGroup.java
│ │ │ │ │ ├── TrackGroupArray.java
│ │ │ │ │ ├── UnrecognizedInputFormatException.java
│ │ │ │ │ ├── ads/
│ │ │ │ │ │ ├── AdPlaybackState.java
│ │ │ │ │ │ ├── AdsLoader.java
│ │ │ │ │ │ ├── AdsMediaSource.java
│ │ │ │ │ │ └── SinglePeriodAdTimeline.java
│ │ │ │ │ └── chunk/
│ │ │ │ │ ├── BaseMediaChunk.java
│ │ │ │ │ ├── BaseMediaChunkIterator.java
│ │ │ │ │ ├── BaseMediaChunkOutput.java
│ │ │ │ │ ├── Chunk.java
│ │ │ │ │ ├── ChunkExtractorWrapper.java
│ │ │ │ │ ├── ChunkHolder.java
│ │ │ │ │ ├── ChunkSampleStream.java
│ │ │ │ │ ├── ChunkSource.java
│ │ │ │ │ ├── ContainerMediaChunk.java
│ │ │ │ │ ├── DataChunk.java
│ │ │ │ │ ├── InitializationChunk.java
│ │ │ │ │ ├── MediaChunk.java
│ │ │ │ │ ├── MediaChunkIterator.java
│ │ │ │ │ ├── MediaChunkListIterator.java
│ │ │ │ │ └── SingleSampleMediaChunk.java
│ │ │ │ ├── text/
│ │ │ │ │ ├── CaptionStyleCompat.java
│ │ │ │ │ ├── Cue.java
│ │ │ │ │ ├── SimpleSubtitleDecoder.java
│ │ │ │ │ ├── SimpleSubtitleOutputBuffer.java
│ │ │ │ │ ├── Subtitle.java
│ │ │ │ │ ├── SubtitleDecoder.java
│ │ │ │ │ ├── SubtitleDecoderException.java
│ │ │ │ │ ├── SubtitleDecoderFactory.java
│ │ │ │ │ ├── SubtitleInputBuffer.java
│ │ │ │ │ ├── SubtitleOutputBuffer.java
│ │ │ │ │ ├── TextOutput.java
│ │ │ │ │ ├── TextRenderer.java
│ │ │ │ │ ├── cea/
│ │ │ │ │ │ ├── Cea608Decoder.java
│ │ │ │ │ │ ├── Cea708Cue.java
│ │ │ │ │ │ ├── Cea708Decoder.java
│ │ │ │ │ │ ├── Cea708InitializationData.java
│ │ │ │ │ │ ├── CeaDecoder.java
│ │ │ │ │ │ ├── CeaSubtitle.java
│ │ │ │ │ │ └── CeaUtil.java
│ │ │ │ │ ├── dvb/
│ │ │ │ │ │ ├── DvbDecoder.java
│ │ │ │ │ │ ├── DvbParser.java
│ │ │ │ │ │ └── DvbSubtitle.java
│ │ │ │ │ ├── pgs/
│ │ │ │ │ │ ├── PgsDecoder.java
│ │ │ │ │ │ └── PgsSubtitle.java
│ │ │ │ │ ├── ssa/
│ │ │ │ │ │ ├── SsaDecoder.java
│ │ │ │ │ │ └── SsaSubtitle.java
│ │ │ │ │ ├── subrip/
│ │ │ │ │ │ ├── SubripDecoder.java
│ │ │ │ │ │ └── SubripSubtitle.java
│ │ │ │ │ ├── ttml/
│ │ │ │ │ │ ├── TtmlDecoder.java
│ │ │ │ │ │ ├── TtmlNode.java
│ │ │ │ │ │ ├── TtmlRegion.java
│ │ │ │ │ │ ├── TtmlRenderUtil.java
│ │ │ │ │ │ ├── TtmlStyle.java
│ │ │ │ │ │ └── TtmlSubtitle.java
│ │ │ │ │ ├── tx3g/
│ │ │ │ │ │ ├── Tx3gDecoder.java
│ │ │ │ │ │ └── Tx3gSubtitle.java
│ │ │ │ │ └── webvtt/
│ │ │ │ │ ├── CssParser.java
│ │ │ │ │ ├── Mp4WebvttDecoder.java
│ │ │ │ │ ├── Mp4WebvttSubtitle.java
│ │ │ │ │ ├── WebvttCssStyle.java
│ │ │ │ │ ├── WebvttCue.java
│ │ │ │ │ ├── WebvttCueParser.java
│ │ │ │ │ ├── WebvttDecoder.java
│ │ │ │ │ ├── WebvttParserUtil.java
│ │ │ │ │ └── WebvttSubtitle.java
│ │ │ │ ├── trackselection/
│ │ │ │ │ ├── AdaptiveTrackSelection.java
│ │ │ │ │ ├── BaseTrackSelection.java
│ │ │ │ │ ├── BufferSizeAdaptationBuilder.java
│ │ │ │ │ ├── DefaultTrackSelector.java
│ │ │ │ │ ├── FixedTrackSelection.java
│ │ │ │ │ ├── MappingTrackSelector.java
│ │ │ │ │ ├── RandomTrackSelection.java
│ │ │ │ │ ├── TrackBitrateEstimator.java
│ │ │ │ │ ├── TrackSelection.java
│ │ │ │ │ ├── TrackSelectionArray.java
│ │ │ │ │ ├── TrackSelectionParameters.java
│ │ │ │ │ ├── TrackSelectionUtil.java
│ │ │ │ │ ├── TrackSelector.java
│ │ │ │ │ ├── TrackSelectorResult.java
│ │ │ │ │ └── WindowedTrackBitrateEstimator.java
│ │ │ │ ├── upstream/
│ │ │ │ │ ├── Allocation.java
│ │ │ │ │ ├── Allocator.java
│ │ │ │ │ ├── AssetDataSource.java
│ │ │ │ │ ├── BandwidthMeter.java
│ │ │ │ │ ├── BaseDataSource.java
│ │ │ │ │ ├── ByteArrayDataSink.java
│ │ │ │ │ ├── ByteArrayDataSource.java
│ │ │ │ │ ├── ContentDataSource.java
│ │ │ │ │ ├── DataSchemeDataSource.java
│ │ │ │ │ ├── DataSink.java
│ │ │ │ │ ├── DataSource.java
│ │ │ │ │ ├── DataSourceException.java
│ │ │ │ │ ├── DataSourceInputStream.java
│ │ │ │ │ ├── DataSpec.java
│ │ │ │ │ ├── DefaultAllocator.java
│ │ │ │ │ ├── DefaultBandwidthMeter.java
│ │ │ │ │ ├── DefaultDataSource.java
│ │ │ │ │ ├── DefaultDataSourceFactory.java
│ │ │ │ │ ├── DefaultHttpDataSource.java
│ │ │ │ │ ├── DefaultHttpDataSourceFactory.java
│ │ │ │ │ ├── DefaultLoadErrorHandlingPolicy.java
│ │ │ │ │ ├── DummyDataSource.java
│ │ │ │ │ ├── FileDataSource.java
│ │ │ │ │ ├── FileDataSourceFactory.java
│ │ │ │ │ ├── HttpDataSource.java
│ │ │ │ │ ├── LoadErrorHandlingPolicy.java
│ │ │ │ │ ├── Loader.java
│ │ │ │ │ ├── LoaderErrorThrower.java
│ │ │ │ │ ├── ParsingLoadable.java
│ │ │ │ │ ├── PriorityDataSource.java
│ │ │ │ │ ├── PriorityDataSourceFactory.java
│ │ │ │ │ ├── RawResourceDataSource.java
│ │ │ │ │ ├── ResolvingDataSource.java
│ │ │ │ │ ├── StatsDataSource.java
│ │ │ │ │ ├── TeeDataSource.java
│ │ │ │ │ ├── TransferListener.java
│ │ │ │ │ ├── UdpDataSource.java
│ │ │ │ │ ├── cache/
│ │ │ │ │ │ ├── Cache.java
│ │ │ │ │ │ ├── CacheDataSink.java
│ │ │ │ │ │ ├── CacheDataSinkFactory.java
│ │ │ │ │ │ ├── CacheDataSource.java
│ │ │ │ │ │ ├── CacheDataSourceFactory.java
│ │ │ │ │ │ ├── CacheEvictor.java
│ │ │ │ │ │ ├── CacheFileMetadata.java
│ │ │ │ │ │ ├── CacheFileMetadataIndex.java
│ │ │ │ │ │ ├── CacheKeyFactory.java
│ │ │ │ │ │ ├── CacheSpan.java
│ │ │ │ │ │ ├── CacheUtil.java
│ │ │ │ │ │ ├── CachedContent.java
│ │ │ │ │ │ ├── CachedContentIndex.java
│ │ │ │ │ │ ├── CachedRegionTracker.java
│ │ │ │ │ │ ├── ContentMetadata.java
│ │ │ │ │ │ ├── ContentMetadataMutations.java
│ │ │ │ │ │ ├── DefaultContentMetadata.java
│ │ │ │ │ │ ├── LeastRecentlyUsedCacheEvictor.java
│ │ │ │ │ │ ├── NoOpCacheEvictor.java
│ │ │ │ │ │ ├── SimpleCache.java
│ │ │ │ │ │ └── SimpleCacheSpan.java
│ │ │ │ │ └── crypto/
│ │ │ │ │ ├── AesCipherDataSink.java
│ │ │ │ │ ├── AesCipherDataSource.java
│ │ │ │ │ ├── AesFlushingCipher.java
│ │ │ │ │ └── CryptoUtil.java
│ │ │ │ ├── util/
│ │ │ │ │ ├── AmazonQuirks.java
│ │ │ │ │ ├── Assertions.java
│ │ │ │ │ ├── AtomicFile.java
│ │ │ │ │ ├── Clock.java
│ │ │ │ │ ├── CodecSpecificDataUtil.java
│ │ │ │ │ ├── ColorParser.java
│ │ │ │ │ ├── ConditionVariable.java
│ │ │ │ │ ├── EGLSurfaceTexture.java
│ │ │ │ │ ├── ErrorMessageProvider.java
│ │ │ │ │ ├── EventDispatcher.java
│ │ │ │ │ ├── EventLogger.java
│ │ │ │ │ ├── FlacStreamMetadata.java
│ │ │ │ │ ├── GlUtil.java
│ │ │ │ │ ├── HandlerWrapper.java
│ │ │ │ │ ├── LibraryLoader.java
│ │ │ │ │ ├── Log.java
│ │ │ │ │ ├── Logger.java
│ │ │ │ │ ├── LongArray.java
│ │ │ │ │ ├── MediaClock.java
│ │ │ │ │ ├── MimeTypes.java
│ │ │ │ │ ├── NalUnitUtil.java
│ │ │ │ │ ├── NotificationUtil.java
│ │ │ │ │ ├── ParsableBitArray.java
│ │ │ │ │ ├── ParsableByteArray.java
│ │ │ │ │ ├── ParsableNalUnitBitArray.java
│ │ │ │ │ ├── Predicate.java
│ │ │ │ │ ├── PriorityTaskManager.java
│ │ │ │ │ ├── RepeatModeUtil.java
│ │ │ │ │ ├── ReusableBufferedOutputStream.java
│ │ │ │ │ ├── SlidingPercentile.java
│ │ │ │ │ ├── StandaloneMediaClock.java
│ │ │ │ │ ├── SystemClock.java
│ │ │ │ │ ├── SystemHandlerWrapper.java
│ │ │ │ │ ├── TimedValueQueue.java
│ │ │ │ │ ├── TimestampAdjuster.java
│ │ │ │ │ ├── TraceUtil.java
│ │ │ │ │ ├── UriUtil.java
│ │ │ │ │ ├── Util.java
│ │ │ │ │ └── XmlPullParserUtil.java
│ │ │ │ └── video/
│ │ │ │ ├── AvcConfig.java
│ │ │ │ ├── ColorInfo.java
│ │ │ │ ├── DolbyVisionConfig.java
│ │ │ │ ├── DummySurface.java
│ │ │ │ ├── HevcConfig.java
│ │ │ │ ├── MediaCodecVideoRenderer.java
│ │ │ │ ├── VideoFrameMetadataListener.java
│ │ │ │ ├── VideoFrameReleaseTimeHelper.java
│ │ │ │ ├── VideoListener.java
│ │ │ │ ├── VideoRendererEventListener.java
│ │ │ │ └── spherical/
│ │ │ │ ├── CameraMotionListener.java
│ │ │ │ ├── CameraMotionRenderer.java
│ │ │ │ ├── FrameRotationQueue.java
│ │ │ │ ├── Projection.java
│ │ │ │ └── ProjectionDecoder.java
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── assets/
│ │ │ │ ├── amr/
│ │ │ │ │ ├── sample_nb.amr
│ │ │ │ │ ├── sample_nb.amr.0.dump
│ │ │ │ │ ├── sample_nb_cbr.amr
│ │ │ │ │ ├── sample_nb_cbr.amr.0.dump
│ │ │ │ │ ├── sample_nb_cbr.amr.1.dump
│ │ │ │ │ ├── sample_nb_cbr.amr.2.dump
│ │ │ │ │ ├── sample_nb_cbr.amr.3.dump
│ │ │ │ │ ├── sample_nb_cbr.amr.unklen.dump
│ │ │ │ │ ├── sample_wb.amr
│ │ │ │ │ ├── sample_wb.amr.0.dump
│ │ │ │ │ ├── sample_wb_cbr.amr
│ │ │ │ │ ├── sample_wb_cbr.amr.0.dump
│ │ │ │ │ ├── sample_wb_cbr.amr.1.dump
│ │ │ │ │ ├── sample_wb_cbr.amr.2.dump
│ │ │ │ │ ├── sample_wb_cbr.amr.3.dump
│ │ │ │ │ └── sample_wb_cbr.amr.unklen.dump
│ │ │ │ ├── download-actions/
│ │ │ │ │ ├── dash-download-v0
│ │ │ │ │ ├── dash-remove-v0
│ │ │ │ │ ├── hls-download-v0
│ │ │ │ │ ├── hls-download-v1
│ │ │ │ │ ├── hls-remove-v0
│ │ │ │ │ ├── hls-remove-v1
│ │ │ │ │ ├── progressive-download-v0
│ │ │ │ │ ├── progressive-remove-v0
│ │ │ │ │ ├── ss-download-v0
│ │ │ │ │ ├── ss-download-v1
│ │ │ │ │ ├── ss-remove-v0
│ │ │ │ │ └── ss-remove-v1
│ │ │ │ ├── flv/
│ │ │ │ │ ├── sample.flv
│ │ │ │ │ └── sample.flv.0.dump
│ │ │ │ ├── mkv/
│ │ │ │ │ ├── sample.mkv
│ │ │ │ │ ├── sample.mkv.0.dump
│ │ │ │ │ ├── sample.mkv.1.dump
│ │ │ │ │ ├── sample.mkv.2.dump
│ │ │ │ │ ├── sample.mkv.3.dump
│ │ │ │ │ ├── subsample_encrypted_altref.webm
│ │ │ │ │ ├── subsample_encrypted_altref.webm.0.dump
│ │ │ │ │ ├── subsample_encrypted_noaltref.webm
│ │ │ │ │ └── subsample_encrypted_noaltref.webm.0.dump
│ │ │ │ ├── mp3/
│ │ │ │ │ ├── bear.mp3.0.dump
│ │ │ │ │ ├── bear.mp3.1.dump
│ │ │ │ │ ├── bear.mp3.2.dump
│ │ │ │ │ ├── bear.mp3.3.dump
│ │ │ │ │ ├── play-trimmed.mp3.0.dump
│ │ │ │ │ ├── play-trimmed.mp3.1.dump
│ │ │ │ │ ├── play-trimmed.mp3.2.dump
│ │ │ │ │ ├── play-trimmed.mp3.3.dump
│ │ │ │ │ └── play-trimmed.mp3.unklen.dump
│ │ │ │ ├── mp4/
│ │ │ │ │ ├── sample.mp4.0.dump
│ │ │ │ │ ├── sample.mp4.1.dump
│ │ │ │ │ ├── sample.mp4.2.dump
│ │ │ │ │ ├── sample.mp4.3.dump
│ │ │ │ │ ├── sample_fragmented.mp4.0.dump
│ │ │ │ │ ├── sample_fragmented_seekable.mp4.0.dump
│ │ │ │ │ ├── sample_fragmented_seekable.mp4.1.dump
│ │ │ │ │ ├── sample_fragmented_seekable.mp4.2.dump
│ │ │ │ │ ├── sample_fragmented_seekable.mp4.3.dump
│ │ │ │ │ └── sample_fragmented_sei.mp4.0.dump
│ │ │ │ ├── offline/
│ │ │ │ │ ├── action_file_for_download_index_upgrade.exi
│ │ │ │ │ ├── action_file_incomplete_header.exi
│ │ │ │ │ ├── action_file_no_data.exi
│ │ │ │ │ ├── action_file_one_action.exi
│ │ │ │ │ ├── action_file_two_actions.exi
│ │ │ │ │ ├── action_file_unsupported_version.exi
│ │ │ │ │ └── action_file_zero_actions.exi
│ │ │ │ ├── ogg/
│ │ │ │ │ ├── bear.opus
│ │ │ │ │ ├── bear.opus.0.dump
│ │ │ │ │ ├── bear.opus.1.dump
│ │ │ │ │ ├── bear.opus.2.dump
│ │ │ │ │ ├── bear.opus.3.dump
│ │ │ │ │ ├── bear.opus.unklen.dump
│ │ │ │ │ ├── bear_flac.ogg
│ │ │ │ │ ├── bear_flac.ogg.0.dump
│ │ │ │ │ ├── bear_flac.ogg.1.dump
│ │ │ │ │ ├── bear_flac.ogg.2.dump
│ │ │ │ │ ├── bear_flac.ogg.3.dump
│ │ │ │ │ ├── bear_flac.ogg.unklen.dump
│ │ │ │ │ ├── bear_flac_noseektable.ogg
│ │ │ │ │ ├── bear_flac_noseektable.ogg.0.dump
│ │ │ │ │ ├── bear_flac_noseektable.ogg.1.dump
│ │ │ │ │ ├── bear_flac_noseektable.ogg.2.dump
│ │ │ │ │ ├── bear_flac_noseektable.ogg.3.dump
│ │ │ │ │ ├── bear_flac_noseektable.ogg.unklen.dump
│ │ │ │ │ ├── bear_vorbis.ogg
│ │ │ │ │ ├── bear_vorbis.ogg.0.dump
│ │ │ │ │ ├── bear_vorbis.ogg.1.dump
│ │ │ │ │ ├── bear_vorbis.ogg.2.dump
│ │ │ │ │ ├── bear_vorbis.ogg.3.dump
│ │ │ │ │ └── bear_vorbis.ogg.unklen.dump
│ │ │ │ ├── rawcc/
│ │ │ │ │ ├── sample.rawcc
│ │ │ │ │ └── sample.rawcc.0.dump
│ │ │ │ ├── ssa/
│ │ │ │ │ ├── empty
│ │ │ │ │ ├── invalid_timecodes
│ │ │ │ │ ├── no_end_timecodes
│ │ │ │ │ ├── typical
│ │ │ │ │ ├── typical_dialogue
│ │ │ │ │ ├── typical_format
│ │ │ │ │ └── typical_header
│ │ │ │ ├── subrip/
│ │ │ │ │ ├── empty
│ │ │ │ │ ├── no_end_timecodes
│ │ │ │ │ ├── typical
│ │ │ │ │ ├── typical_extra_blank_line
│ │ │ │ │ ├── typical_missing_sequence
│ │ │ │ │ ├── typical_missing_timecode
│ │ │ │ │ ├── typical_negative_timestamps
│ │ │ │ │ ├── typical_unexpected_end
│ │ │ │ │ ├── typical_with_byte_order_mark
│ │ │ │ │ └── typical_with_tags
│ │ │ │ ├── ts/
│ │ │ │ │ ├── bbb_2500ms.ts
│ │ │ │ │ ├── elephants_dream.mpg
│ │ │ │ │ ├── sample.ac3
│ │ │ │ │ ├── sample.ac3.0.dump
│ │ │ │ │ ├── sample.ac4
│ │ │ │ │ ├── sample.ac4.0.dump
│ │ │ │ │ ├── sample.adts
│ │ │ │ │ ├── sample.adts.0.dump
│ │ │ │ │ ├── sample.eac3
│ │ │ │ │ ├── sample.eac3.0.dump
│ │ │ │ │ ├── sample.ps
│ │ │ │ │ ├── sample.ps.0.dump
│ │ │ │ │ ├── sample.ps.1.dump
│ │ │ │ │ ├── sample.ps.2.dump
│ │ │ │ │ ├── sample.ps.3.dump
│ │ │ │ │ ├── sample.ps.unklen.dump
│ │ │ │ │ ├── sample.ts
│ │ │ │ │ ├── sample.ts.0.dump
│ │ │ │ │ ├── sample.ts.1.dump
│ │ │ │ │ ├── sample.ts.2.dump
│ │ │ │ │ ├── sample.ts.3.dump
│ │ │ │ │ ├── sample.ts.unklen.dump
│ │ │ │ │ ├── sample_cbs.adts
│ │ │ │ │ ├── sample_cbs.adts.0.dump
│ │ │ │ │ ├── sample_cbs.adts.1.dump
│ │ │ │ │ ├── sample_cbs.adts.2.dump
│ │ │ │ │ ├── sample_cbs.adts.3.dump
│ │ │ │ │ ├── sample_cbs.adts.unklen.dump
│ │ │ │ │ └── sample_with_sdt.ts
│ │ │ │ ├── ttml/
│ │ │ │ │ ├── bitmap_percentage_region.xml
│ │ │ │ │ ├── bitmap_pixel_region.xml
│ │ │ │ │ ├── bitmap_unsupported_region.xml
│ │ │ │ │ ├── chain_multiple_styles.xml
│ │ │ │ │ ├── font_size.xml
│ │ │ │ │ ├── font_size_empty.xml
│ │ │ │ │ ├── font_size_invalid.xml
│ │ │ │ │ ├── font_size_no_unit.xml
│ │ │ │ │ ├── frame_rate.xml
│ │ │ │ │ ├── inherit_and_override_style.xml
│ │ │ │ │ ├── inherit_global_and_parent.xml
│ │ │ │ │ ├── inherit_multiple_styles.xml
│ │ │ │ │ ├── inherit_style.xml
│ │ │ │ │ ├── inline_style_attributes.xml
│ │ │ │ │ ├── multiple_regions.xml
│ │ │ │ │ └── no_underline_linethrough.xml
│ │ │ │ ├── tx3g/
│ │ │ │ │ ├── initialization
│ │ │ │ │ ├── initialization_all_defaults
│ │ │ │ │ ├── no_subtitle
│ │ │ │ │ ├── sample_just_text
│ │ │ │ │ ├── sample_utf16_be_no_styl
│ │ │ │ │ ├── sample_utf16_le_no_styl
│ │ │ │ │ ├── sample_with_multiple_styl
│ │ │ │ │ ├── sample_with_other_extension
│ │ │ │ │ ├── sample_with_styl
│ │ │ │ │ ├── sample_with_styl_all_defaults
│ │ │ │ │ └── sample_with_tbox
│ │ │ │ ├── wav/
│ │ │ │ │ ├── sample.wav.0.dump
│ │ │ │ │ ├── sample.wav.1.dump
│ │ │ │ │ ├── sample.wav.2.dump
│ │ │ │ │ └── sample.wav.3.dump
│ │ │ │ ├── webm/
│ │ │ │ │ └── vorbis_codec_private
│ │ │ │ └── webvtt/
│ │ │ │ ├── empty
│ │ │ │ ├── typical
│ │ │ │ ├── typical_with_bad_timestamps
│ │ │ │ ├── typical_with_comments
│ │ │ │ ├── typical_with_identifiers
│ │ │ │ ├── with_bad_cue_header
│ │ │ │ ├── with_bom
│ │ │ │ ├── with_css_complex_selectors
│ │ │ │ ├── with_css_styles
│ │ │ │ ├── with_positioning
│ │ │ │ └── with_tags
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ ├── CTest.java
│ │ │ ├── DefaultLoadControlTest.java
│ │ │ ├── DefaultMediaClockTest.java
│ │ │ ├── ExoPlayerTest.java
│ │ │ ├── FormatTest.java
│ │ │ ├── MediaPeriodQueueTest.java
│ │ │ ├── TimelineTest.java
│ │ │ ├── analytics/
│ │ │ │ └── AnalyticsCollectorTest.java
│ │ │ ├── audio/
│ │ │ │ ├── Ac3UtilTest.java
│ │ │ │ ├── AudioFocusManagerTest.java
│ │ │ │ ├── DefaultAudioSinkTest.java
│ │ │ │ ├── SilenceSkippingAudioProcessorTest.java
│ │ │ │ ├── SimpleDecoderAudioRendererTest.java
│ │ │ │ └── SonicAudioProcessorTest.java
│ │ │ ├── database/
│ │ │ │ └── VersionTableTest.java
│ │ │ ├── drm/
│ │ │ │ ├── ClearKeyUtilTest.java
│ │ │ │ ├── DrmInitDataTest.java
│ │ │ │ └── OfflineLicenseHelperTest.java
│ │ │ ├── extractor/
│ │ │ │ ├── ConstantBitrateSeekMapTest.java
│ │ │ │ ├── DefaultExtractorInputTest.java
│ │ │ │ ├── DefaultExtractorsFactoryTest.java
│ │ │ │ ├── ExtractorTest.java
│ │ │ │ ├── Id3PeekerTest.java
│ │ │ │ ├── amr/
│ │ │ │ │ ├── AmrExtractorSeekTest.java
│ │ │ │ │ └── AmrExtractorTest.java
│ │ │ │ ├── flv/
│ │ │ │ │ └── FlvExtractorTest.java
│ │ │ │ ├── mkv/
│ │ │ │ │ ├── DefaultEbmlReaderTest.java
│ │ │ │ │ ├── MatroskaExtractorTest.java
│ │ │ │ │ └── VarintReaderTest.java
│ │ │ │ ├── mp3/
│ │ │ │ │ ├── Mp3ExtractorTest.java
│ │ │ │ │ └── XingSeekerTest.java
│ │ │ │ ├── mp4/
│ │ │ │ │ ├── AtomParsersTest.java
│ │ │ │ │ ├── FragmentedMp4ExtractorTest.java
│ │ │ │ │ ├── MdtaMetadataEntryTest.java
│ │ │ │ │ ├── Mp4ExtractorTest.java
│ │ │ │ │ └── PsshAtomUtilTest.java
│ │ │ │ ├── ogg/
│ │ │ │ │ ├── DefaultOggSeekerTest.java
│ │ │ │ │ ├── OggExtractorTest.java
│ │ │ │ │ ├── OggPacketTest.java
│ │ │ │ │ ├── OggPageHeaderTest.java
│ │ │ │ │ ├── OggTestFile.java
│ │ │ │ │ ├── VorbisBitArrayTest.java
│ │ │ │ │ ├── VorbisReaderTest.java
│ │ │ │ │ └── VorbisUtilTest.java
│ │ │ │ ├── rawcc/
│ │ │ │ │ └── RawCcExtractorTest.java
│ │ │ │ ├── ts/
│ │ │ │ │ ├── Ac3ExtractorTest.java
│ │ │ │ │ ├── Ac4ExtractorTest.java
│ │ │ │ │ ├── AdtsExtractorSeekTest.java
│ │ │ │ │ ├── AdtsExtractorTest.java
│ │ │ │ │ ├── AdtsReaderTest.java
│ │ │ │ │ ├── PsDurationReaderTest.java
│ │ │ │ │ ├── PsExtractorSeekTest.java
│ │ │ │ │ ├── PsExtractorTest.java
│ │ │ │ │ ├── SectionReaderTest.java
│ │ │ │ │ ├── TsDurationReaderTest.java
│ │ │ │ │ ├── TsExtractorSeekTest.java
│ │ │ │ │ └── TsExtractorTest.java
│ │ │ │ └── wav/
│ │ │ │ └── WavExtractorTest.java
│ │ │ ├── metadata/
│ │ │ │ ├── MetadataRendererTest.java
│ │ │ │ ├── emsg/
│ │ │ │ │ ├── EventMessageDecoderTest.java
│ │ │ │ │ ├── EventMessageEncoderTest.java
│ │ │ │ │ └── EventMessageTest.java
│ │ │ │ ├── flac/
│ │ │ │ │ ├── PictureFrameTest.java
│ │ │ │ │ └── VorbisCommentTest.java
│ │ │ │ ├── icy/
│ │ │ │ │ ├── IcyDecoderTest.java
│ │ │ │ │ ├── IcyHeadersTest.java
│ │ │ │ │ └── IcyInfoTest.java
│ │ │ │ ├── id3/
│ │ │ │ │ ├── ChapterFrameTest.java
│ │ │ │ │ ├── ChapterTocFrameTest.java
│ │ │ │ │ ├── Id3DecoderTest.java
│ │ │ │ │ └── MlltFrameTest.java
│ │ │ │ └── scte35/
│ │ │ │ └── SpliceInfoDecoderTest.java
│ │ │ ├── offline/
│ │ │ │ ├── ActionFileTest.java
│ │ │ │ ├── ActionFileUpgradeUtilTest.java
│ │ │ │ ├── DefaultDownloadIndexTest.java
│ │ │ │ ├── DefaultDownloaderFactoryTest.java
│ │ │ │ ├── DownloadBuilder.java
│ │ │ │ ├── DownloadHelperTest.java
│ │ │ │ ├── DownloadManagerTest.java
│ │ │ │ ├── DownloadRequestTest.java
│ │ │ │ └── StreamKeyTest.java
│ │ │ ├── source/
│ │ │ │ ├── ClippingMediaSourceTest.java
│ │ │ │ ├── CompositeSequenceableLoaderTest.java
│ │ │ │ ├── ConcatenatingMediaSourceTest.java
│ │ │ │ ├── LoopingMediaSourceTest.java
│ │ │ │ ├── MergingMediaSourceTest.java
│ │ │ │ ├── SampleQueueTest.java
│ │ │ │ ├── ShuffleOrderTest.java
│ │ │ │ ├── SinglePeriodTimelineTest.java
│ │ │ │ ├── TrackGroupArrayTest.java
│ │ │ │ ├── TrackGroupTest.java
│ │ │ │ ├── ads/
│ │ │ │ │ └── AdPlaybackStateTest.java
│ │ │ │ └── chunk/
│ │ │ │ └── MediaChunkListIteratorTest.java
│ │ │ ├── text/
│ │ │ │ ├── ssa/
│ │ │ │ │ └── SsaDecoderTest.java
│ │ │ │ ├── subrip/
│ │ │ │ │ └── SubripDecoderTest.java
│ │ │ │ ├── ttml/
│ │ │ │ │ ├── TtmlDecoderTest.java
│ │ │ │ │ ├── TtmlRenderUtilTest.java
│ │ │ │ │ └── TtmlStyleTest.java
│ │ │ │ ├── tx3g/
│ │ │ │ │ └── Tx3gDecoderTest.java
│ │ │ │ └── webvtt/
│ │ │ │ ├── CssParserTest.java
│ │ │ │ ├── Mp4WebvttDecoderTest.java
│ │ │ │ ├── WebvttCueParserTest.java
│ │ │ │ ├── WebvttDecoderTest.java
│ │ │ │ └── WebvttSubtitleTest.java
│ │ │ ├── trackselection/
│ │ │ │ ├── AdaptiveTrackSelectionTest.java
│ │ │ │ ├── BufferSizeAdaptiveTrackSelectionTest.java
│ │ │ │ ├── DefaultTrackSelectorTest.java
│ │ │ │ ├── MappingTrackSelectorTest.java
│ │ │ │ ├── TrackSelectionUtilTest.java
│ │ │ │ ├── TrackSelectorTest.java
│ │ │ │ └── WindowedTrackBitrateEstimatorTest.java
│ │ │ ├── upstream/
│ │ │ │ ├── AssetDataSourceTest.java
│ │ │ │ ├── BaseDataSourceTest.java
│ │ │ │ ├── ByteArrayDataSourceTest.java
│ │ │ │ ├── DataSchemeDataSourceTest.java
│ │ │ │ ├── DataSourceAsserts.java
│ │ │ │ ├── DataSourceInputStreamTest.java
│ │ │ │ ├── DataSpecTest.java
│ │ │ │ ├── DefaultBandwidthMeterTest.java
│ │ │ │ ├── DefaultLoadErrorHandlingPolicyTest.java
│ │ │ │ ├── cache/
│ │ │ │ │ ├── CacheDataSourceTest.java
│ │ │ │ │ ├── CacheDataSourceTest2.java
│ │ │ │ │ ├── CacheUtilTest.java
│ │ │ │ │ ├── CachedContentIndexTest.java
│ │ │ │ │ ├── CachedRegionTrackerTest.java
│ │ │ │ │ ├── DefaultContentMetadataTest.java
│ │ │ │ │ ├── LeastRecentlyUsedCacheEvictorTest.java
│ │ │ │ │ ├── SimpleCacheSpanTest.java
│ │ │ │ │ └── SimpleCacheTest.java
│ │ │ │ └── crypto/
│ │ │ │ └── AesFlushingCipherTest.java
│ │ │ ├── util/
│ │ │ │ ├── AtomicFileTest.java
│ │ │ │ ├── ColorParserTest.java
│ │ │ │ ├── FlacStreamMetadataTest.java
│ │ │ │ ├── MimeTypesTest.java
│ │ │ │ ├── NalUnitUtilTest.java
│ │ │ │ ├── ParsableBitArrayTest.java
│ │ │ │ ├── ParsableByteArrayTest.java
│ │ │ │ ├── ParsableNalUnitBitArrayTest.java
│ │ │ │ ├── ReusableBufferedOutputStreamTest.java
│ │ │ │ ├── TimedValueQueueTest.java
│ │ │ │ ├── UriUtilTest.java
│ │ │ │ └── UtilTest.java
│ │ │ └── video/
│ │ │ └── spherical/
│ │ │ ├── FrameRotationQueueTest.java
│ │ │ ├── ProjectionDecoderTest.java
│ │ │ └── ProjectionTest.java
│ │ ├── dash/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── source/
│ │ │ │ └── dash/
│ │ │ │ ├── DashChunkSource.java
│ │ │ │ ├── DashManifestStaleException.java
│ │ │ │ ├── DashMediaPeriod.java
│ │ │ │ ├── DashMediaSource.java
│ │ │ │ ├── DashSegmentIndex.java
│ │ │ │ ├── DashUtil.java
│ │ │ │ ├── DashWrappingSegmentIndex.java
│ │ │ │ ├── DefaultDashChunkSource.java
│ │ │ │ ├── EventSampleStream.java
│ │ │ │ ├── PlayerEmsgHandler.java
│ │ │ │ ├── manifest/
│ │ │ │ │ ├── AdaptationSet.java
│ │ │ │ │ ├── DashManifest.java
│ │ │ │ │ ├── DashManifestParser.java
│ │ │ │ │ ├── DashManifestParser2.java
│ │ │ │ │ ├── Descriptor.java
│ │ │ │ │ ├── EventStream.java
│ │ │ │ │ ├── Period.java
│ │ │ │ │ ├── ProgramInformation.java
│ │ │ │ │ ├── RangedUri.java
│ │ │ │ │ ├── Representation.java
│ │ │ │ │ ├── SegmentBase.java
│ │ │ │ │ ├── SingleSegmentIndex.java
│ │ │ │ │ ├── UrlTemplate.java
│ │ │ │ │ └── UtcTimingElement.java
│ │ │ │ └── offline/
│ │ │ │ └── DashDownloader.java
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── assets/
│ │ │ │ ├── sample_mpd
│ │ │ │ ├── sample_mpd_event_stream
│ │ │ │ ├── sample_mpd_labels
│ │ │ │ ├── sample_mpd_segment_template
│ │ │ │ └── sample_mpd_unknown_mime_type
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── source/
│ │ │ └── dash/
│ │ │ ├── DashMediaPeriodTest.java
│ │ │ ├── DashMediaSourceTest.java
│ │ │ ├── DashUtilTest.java
│ │ │ ├── EventSampleStreamTest.java
│ │ │ ├── manifest/
│ │ │ │ ├── DashManifestParserTest.java
│ │ │ │ ├── DashManifestTest.java
│ │ │ │ ├── RangedUriTest.java
│ │ │ │ └── UrlTemplateTest.java
│ │ │ └── offline/
│ │ │ ├── DashDownloadTestData.java
│ │ │ ├── DashDownloaderTest.java
│ │ │ ├── DownloadHelperTest.java
│ │ │ ├── DownloadManagerDashTest.java
│ │ │ └── DownloadServiceDashTest.java
│ │ ├── hls/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── source/
│ │ │ │ └── hls/
│ │ │ │ ├── Aes128DataSource.java
│ │ │ │ ├── DefaultHlsDataSourceFactory.java
│ │ │ │ ├── DefaultHlsExtractorFactory.java
│ │ │ │ ├── HlsChunkSource.java
│ │ │ │ ├── HlsDataSourceFactory.java
│ │ │ │ ├── HlsExtractorFactory.java
│ │ │ │ ├── HlsManifest.java
│ │ │ │ ├── HlsMediaChunk.java
│ │ │ │ ├── HlsMediaPeriod.java
│ │ │ │ ├── HlsMediaSource.java
│ │ │ │ ├── HlsMetadataType.java
│ │ │ │ ├── HlsSampleStream.java
│ │ │ │ ├── HlsSampleStreamWrapper.java
│ │ │ │ ├── HlsTrackMetadataEntry.java
│ │ │ │ ├── SampleQueueMappingException.java
│ │ │ │ ├── TimestampAdjusterProvider.java
│ │ │ │ ├── WebvttExtractor.java
│ │ │ │ ├── offline/
│ │ │ │ │ └── HlsDownloader.java
│ │ │ │ └── playlist/
│ │ │ │ ├── DefaultHlsPlaylistParserFactory.java
│ │ │ │ ├── DefaultHlsPlaylistTracker.java
│ │ │ │ ├── FilteringHlsPlaylistParserFactory.java
│ │ │ │ ├── HlsMasterPlaylist.java
│ │ │ │ ├── HlsMediaPlaylist.java
│ │ │ │ ├── HlsPlaylist.java
│ │ │ │ ├── HlsPlaylistParser.java
│ │ │ │ ├── HlsPlaylistParserFactory.java
│ │ │ │ └── HlsPlaylistTracker.java
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── source/
│ │ │ └── hls/
│ │ │ ├── Aes128DataSourceTest.java
│ │ │ ├── HlsMediaPeriodTest.java
│ │ │ ├── WebvttExtractorTest.java
│ │ │ ├── offline/
│ │ │ │ ├── DownloadHelperTest.java
│ │ │ │ ├── HlsDownloadTestData.java
│ │ │ │ └── HlsDownloaderTest.java
│ │ │ └── playlist/
│ │ │ ├── HlsMasterPlaylistParserTest.java
│ │ │ └── HlsMediaPlaylistParserTest.java
│ │ ├── sabr/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── source/
│ │ │ │ └── sabr/
│ │ │ │ ├── DefaultSabrChunkSource.java
│ │ │ │ ├── EventSampleStream.java
│ │ │ │ ├── PlayerEmsgHandler.java
│ │ │ │ ├── SabrChunkSource.java
│ │ │ │ ├── SabrMediaPeriod.java
│ │ │ │ ├── SabrMediaSource.java
│ │ │ │ ├── SabrSegmentIndex.java
│ │ │ │ ├── SabrWrappingSegmentIndex.java
│ │ │ │ ├── manifest/
│ │ │ │ │ ├── AdaptationSet.java
│ │ │ │ │ ├── EventStream.java
│ │ │ │ │ ├── Period.java
│ │ │ │ │ ├── RangedUri.java
│ │ │ │ │ ├── Representation.java
│ │ │ │ │ ├── SabrManifest.java
│ │ │ │ │ ├── SabrManifestParser.java
│ │ │ │ │ ├── SegmentBase.java
│ │ │ │ │ ├── SingleSegmentIndex.java
│ │ │ │ │ └── UrlTemplate.java
│ │ │ │ └── parser/
│ │ │ │ ├── SabrProcessor.java
│ │ │ │ ├── SabrStream.java
│ │ │ │ ├── adapter/
│ │ │ │ │ ├── SabrFragmentedMp4Adapter.java
│ │ │ │ │ └── SabrMatroskaAdapter.java
│ │ │ │ ├── exceptions/
│ │ │ │ │ ├── MediaSegmentMismatchError.java
│ │ │ │ │ ├── PoTokenError.java
│ │ │ │ │ ├── SabrStreamConsumedError.java
│ │ │ │ │ └── SabrStreamError.java
│ │ │ │ ├── frames/
│ │ │ │ │ ├── AACFrameExtractor.java
│ │ │ │ │ ├── AVCFrameExtractor.java
│ │ │ │ │ ├── BaseFrameExtractor.java
│ │ │ │ │ ├── FrameExtractor.java
│ │ │ │ │ ├── OpusFrameExtractor.java
│ │ │ │ │ ├── VP9FrameExtractor.java
│ │ │ │ │ └── VorbisFrameExtractor.java
│ │ │ │ ├── misc/
│ │ │ │ │ ├── EnabledTrackTypes.java
│ │ │ │ │ ├── SabrExtractorInput.java
│ │ │ │ │ └── Utils.java
│ │ │ │ ├── models/
│ │ │ │ │ ├── AudioSelector.java
│ │ │ │ │ ├── CaptionSelector.java
│ │ │ │ │ ├── ConsumedRange.java
│ │ │ │ │ ├── FormatSelector.java
│ │ │ │ │ ├── Segment.java
│ │ │ │ │ ├── SelectedFormat.java
│ │ │ │ │ └── VideoSelector.java
│ │ │ │ ├── parts/
│ │ │ │ │ ├── FormatInitializedSabrPart.java
│ │ │ │ │ ├── MediaSeekSabrPart.java
│ │ │ │ │ ├── MediaSegmentDataSabrPart.java
│ │ │ │ │ ├── MediaSegmentEndSabrPart.java
│ │ │ │ │ ├── MediaSegmentInitSabrPart.java
│ │ │ │ │ ├── PoTokenStatusSabrPart.java
│ │ │ │ │ ├── RefreshPlayerResponseSabrPart.java
│ │ │ │ │ └── SabrPart.java
│ │ │ │ ├── results/
│ │ │ │ │ ├── ProcessFormatInitializationMetadataResult.java
│ │ │ │ │ ├── ProcessLiveMetadataResult.java
│ │ │ │ │ ├── ProcessMediaEndResult.java
│ │ │ │ │ ├── ProcessMediaHeaderResult.java
│ │ │ │ │ ├── ProcessMediaResult.java
│ │ │ │ │ ├── ProcessSabrSeekResult.java
│ │ │ │ │ └── ProcessStreamProtectionStatusResult.java
│ │ │ │ └── ump/
│ │ │ │ ├── UMPDecoder.java
│ │ │ │ ├── UMPEncoder.java
│ │ │ │ ├── UMPInputStream.java
│ │ │ │ ├── UMPPart.java
│ │ │ │ └── UMPPartId.java
│ │ │ └── proto/
│ │ │ └── sabr/
│ │ │ ├── misc/
│ │ │ │ └── common.proto
│ │ │ ├── other/
│ │ │ │ └── ump_part_id.proto
│ │ │ └── videostreaming/
│ │ │ ├── buffered_range.proto
│ │ │ ├── client_abr_state.proto
│ │ │ ├── crypto_params.proto
│ │ │ ├── format_initialization_metadata.proto
│ │ │ ├── innertube_request.proto
│ │ │ ├── live_metadata.proto
│ │ │ ├── media_capabilities.proto
│ │ │ ├── media_header.proto
│ │ │ ├── next_request_policy.proto
│ │ │ ├── onesie_header.proto
│ │ │ ├── onesie_header_type.proto
│ │ │ ├── onesie_innertube_request.proto
│ │ │ ├── onesie_innertube_response.proto
│ │ │ ├── onesie_proxy_status.proto
│ │ │ ├── onesie_request.proto
│ │ │ ├── playback_cookie.proto
│ │ │ ├── reload_player_response.proto
│ │ │ ├── sabr_context_sending_policy.proto
│ │ │ ├── sabr_context_update.proto
│ │ │ ├── sabr_error.proto
│ │ │ ├── sabr_redirect.proto
│ │ │ ├── sabr_seek.proto
│ │ │ ├── stream_protection_status.proto
│ │ │ ├── streamer_context.proto
│ │ │ ├── time_range.proto
│ │ │ └── video_playback_abr_request.proto
│ │ ├── smoothstreaming/
│ │ │ ├── README.md
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ ├── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── source/
│ │ │ │ └── smoothstreaming/
│ │ │ │ ├── DefaultSsChunkSource.java
│ │ │ │ ├── SsChunkSource.java
│ │ │ │ ├── SsMediaPeriod.java
│ │ │ │ ├── SsMediaSource.java
│ │ │ │ ├── manifest/
│ │ │ │ │ ├── SsManifest.java
│ │ │ │ │ ├── SsManifestParser.java
│ │ │ │ │ └── SsUtil.java
│ │ │ │ └── offline/
│ │ │ │ └── SsDownloader.java
│ │ │ └── test/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── assets/
│ │ │ │ ├── sample_ismc_1
│ │ │ │ └── sample_ismc_2
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── source/
│ │ │ └── smoothstreaming/
│ │ │ ├── SsMediaPeriodTest.java
│ │ │ ├── SsTestUtils.java
│ │ │ ├── manifest/
│ │ │ │ ├── SsManifestParserTest.java
│ │ │ │ └── SsManifestTest.java
│ │ │ └── offline/
│ │ │ ├── DownloadHelperTest.java
│ │ │ └── SsDownloaderTest.java
│ │ └── ui/
│ │ ├── README.md
│ │ ├── build.gradle
│ │ └── src/
│ │ ├── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── ui/
│ │ │ │ ├── AspectRatioFrameLayout.java
│ │ │ │ ├── DebugTextViewHelper.java
│ │ │ │ ├── DefaultTimeBar.java
│ │ │ │ ├── DefaultTrackNameProvider.java
│ │ │ │ ├── DownloadNotificationHelper.java
│ │ │ │ ├── DownloadNotificationUtil.java
│ │ │ │ ├── PlaybackControlView.java
│ │ │ │ ├── PlayerControlView.java
│ │ │ │ ├── PlayerNotificationManager.java
│ │ │ │ ├── PlayerView.java
│ │ │ │ ├── SimpleExoPlayerView.java
│ │ │ │ ├── SubtitlePainter.java
│ │ │ │ ├── SubtitleView.java
│ │ │ │ ├── TimeBar.java
│ │ │ │ ├── TrackNameProvider.java
│ │ │ │ ├── TrackSelectionDialogBuilder.java
│ │ │ │ ├── TrackSelectionView.java
│ │ │ │ └── spherical/
│ │ │ │ ├── CanvasRenderer.java
│ │ │ │ ├── GlViewGroup.java
│ │ │ │ ├── OrientationListener.java
│ │ │ │ ├── PointerRenderer.java
│ │ │ │ ├── ProjectionRenderer.java
│ │ │ │ ├── SceneRenderer.java
│ │ │ │ ├── SingleTapListener.java
│ │ │ │ ├── SphericalSurfaceView.java
│ │ │ │ └── TouchTracker.java
│ │ │ └── res/
│ │ │ ├── drawable/
│ │ │ │ └── exo_edit_mode_logo.xml
│ │ │ ├── drawable-anydpi-v21/
│ │ │ │ ├── exo_controls_fullscreen_enter.xml
│ │ │ │ ├── exo_controls_fullscreen_exit.xml
│ │ │ │ ├── exo_controls_repeat_all.xml
│ │ │ │ ├── exo_controls_repeat_off.xml
│ │ │ │ ├── exo_controls_repeat_one.xml
│ │ │ │ ├── exo_controls_shuffle_off.xml
│ │ │ │ ├── exo_controls_shuffle_on.xml
│ │ │ │ ├── exo_icon_fastforward.xml
│ │ │ │ ├── exo_icon_next.xml
│ │ │ │ ├── exo_icon_pause.xml
│ │ │ │ ├── exo_icon_play.xml
│ │ │ │ ├── exo_icon_previous.xml
│ │ │ │ ├── exo_icon_rewind.xml
│ │ │ │ └── exo_icon_stop.xml
│ │ │ ├── layout/
│ │ │ │ ├── exo_list_divider.xml
│ │ │ │ ├── exo_playback_control_view.xml
│ │ │ │ ├── exo_player_control_view.xml
│ │ │ │ ├── exo_player_view.xml
│ │ │ │ ├── exo_simple_player_view.xml
│ │ │ │ └── exo_track_selection_dialog.xml
│ │ │ ├── values/
│ │ │ │ ├── attrs.xml
│ │ │ │ ├── constants.xml
│ │ │ │ ├── drawables.xml
│ │ │ │ ├── ids.xml
│ │ │ │ ├── strings.xml
│ │ │ │ └── styles.xml
│ │ │ ├── values-af/
│ │ │ │ └── strings.xml
│ │ │ ├── values-am/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ar/
│ │ │ │ └── strings.xml
│ │ │ ├── values-az/
│ │ │ │ └── strings.xml
│ │ │ ├── values-b+sr+Latn/
│ │ │ │ └── strings.xml
│ │ │ ├── values-be/
│ │ │ │ └── strings.xml
│ │ │ ├── values-bg/
│ │ │ │ └── strings.xml
│ │ │ ├── values-bn/
│ │ │ │ └── strings.xml
│ │ │ ├── values-bs/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ca/
│ │ │ │ └── strings.xml
│ │ │ ├── values-cs/
│ │ │ │ └── strings.xml
│ │ │ ├── values-da/
│ │ │ │ └── strings.xml
│ │ │ ├── values-de/
│ │ │ │ └── strings.xml
│ │ │ ├── values-el/
│ │ │ │ └── strings.xml
│ │ │ ├── values-en-rAU/
│ │ │ │ └── strings.xml
│ │ │ ├── values-en-rGB/
│ │ │ │ └── strings.xml
│ │ │ ├── values-en-rIN/
│ │ │ │ └── strings.xml
│ │ │ ├── values-es/
│ │ │ │ └── strings.xml
│ │ │ ├── values-es-rUS/
│ │ │ │ └── strings.xml
│ │ │ ├── values-et/
│ │ │ │ └── strings.xml
│ │ │ ├── values-eu/
│ │ │ │ └── strings.xml
│ │ │ ├── values-fa/
│ │ │ │ └── strings.xml
│ │ │ ├── values-fi/
│ │ │ │ └── strings.xml
│ │ │ ├── values-fr/
│ │ │ │ └── strings.xml
│ │ │ ├── values-fr-rCA/
│ │ │ │ └── strings.xml
│ │ │ ├── values-gl/
│ │ │ │ └── strings.xml
│ │ │ ├── values-gu/
│ │ │ │ └── strings.xml
│ │ │ ├── values-hi/
│ │ │ │ └── strings.xml
│ │ │ ├── values-hr/
│ │ │ │ └── strings.xml
│ │ │ ├── values-hu/
│ │ │ │ └── strings.xml
│ │ │ ├── values-hy/
│ │ │ │ └── strings.xml
│ │ │ ├── values-in/
│ │ │ │ └── strings.xml
│ │ │ ├── values-is/
│ │ │ │ └── strings.xml
│ │ │ ├── values-it/
│ │ │ │ └── strings.xml
│ │ │ ├── values-iw/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ja/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ka/
│ │ │ │ └── strings.xml
│ │ │ ├── values-kk/
│ │ │ │ └── strings.xml
│ │ │ ├── values-km/
│ │ │ │ └── strings.xml
│ │ │ ├── values-kn/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ko/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ky/
│ │ │ │ └── strings.xml
│ │ │ ├── values-lo/
│ │ │ │ └── strings.xml
│ │ │ ├── values-lt/
│ │ │ │ └── strings.xml
│ │ │ ├── values-lv/
│ │ │ │ └── strings.xml
│ │ │ ├── values-mk/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ml/
│ │ │ │ └── strings.xml
│ │ │ ├── values-mn/
│ │ │ │ └── strings.xml
│ │ │ ├── values-mr/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ms/
│ │ │ │ └── strings.xml
│ │ │ ├── values-my/
│ │ │ │ └── strings.xml
│ │ │ ├── values-nb/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ne/
│ │ │ │ └── strings.xml
│ │ │ ├── values-nl/
│ │ │ │ └── strings.xml
│ │ │ ├── values-pa/
│ │ │ │ └── strings.xml
│ │ │ ├── values-pl/
│ │ │ │ └── strings.xml
│ │ │ ├── values-pt/
│ │ │ │ └── strings.xml
│ │ │ ├── values-pt-rPT/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ro/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ru/
│ │ │ │ └── strings.xml
│ │ │ ├── values-si/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sk/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sl/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sq/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sr/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sv/
│ │ │ │ └── strings.xml
│ │ │ ├── values-sw/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ta/
│ │ │ │ └── strings.xml
│ │ │ ├── values-te/
│ │ │ │ └── strings.xml
│ │ │ ├── values-th/
│ │ │ │ └── strings.xml
│ │ │ ├── values-tl/
│ │ │ │ └── strings.xml
│ │ │ ├── values-tr/
│ │ │ │ └── strings.xml
│ │ │ ├── values-uk/
│ │ │ │ └── strings.xml
│ │ │ ├── values-ur/
│ │ │ │ └── strings.xml
│ │ │ ├── values-uz/
│ │ │ │ └── strings.xml
│ │ │ ├── values-vi/
│ │ │ │ └── strings.xml
│ │ │ ├── values-zh-rCN/
│ │ │ │ └── strings.xml
│ │ │ ├── values-zh-rHK/
│ │ │ │ └── strings.xml
│ │ │ ├── values-zh-rTW/
│ │ │ │ └── strings.xml
│ │ │ └── values-zu/
│ │ │ └── strings.xml
│ │ └── test/
│ │ ├── AndroidManifest.xml
│ │ └── java/
│ │ └── com/
│ │ └── google/
│ │ └── android/
│ │ └── exoplayer2/
│ │ └── ui/
│ │ └── spherical/
│ │ ├── CanvasRendererTest.java
│ │ └── TouchTrackerTest.java
│ ├── playbacktests/
│ │ ├── build.gradle
│ │ └── src/
│ │ ├── androidTest/
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── android/
│ │ │ └── exoplayer2/
│ │ │ └── playbacktests/
│ │ │ └── gts/
│ │ │ ├── CommonEncryptionDrmTest.java
│ │ │ ├── DashDownloadTest.java
│ │ │ ├── DashStreamingTest.java
│ │ │ ├── DashTestData.java
│ │ │ ├── DashTestRunner.java
│ │ │ ├── DashWidevineOfflineTest.java
│ │ │ └── EnumerateDecodersTest.java
│ │ └── main/
│ │ └── AndroidManifest.xml
│ ├── publish.gradle
│ ├── settings.gradle
│ ├── testutils/
│ │ ├── build.gradle
│ │ └── src/
│ │ ├── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java/
│ │ │ │ └── com/
│ │ │ │ └── google/
│ │ │ │ └── android/
│ │ │ │ └── exoplayer2/
│ │ │ │ └── testutil/
│ │ │ │ ├── Action.java
│ │ │ │ ├── ActionSchedule.java
│ │ │ │ ├── AutoAdvancingFakeClock.java
│ │ │ │ ├── DebugRenderersFactory.java
│ │ │ │ ├── DecoderCountersUtil.java
│ │ │ │ ├── DummyMainThread.java
│ │ │ │ ├── Dumper.java
│ │ │ │ ├── ExoHostedTest.java
│ │ │ │ ├── ExoPlayerTestRunner.java
│ │ │ │ ├── ExtractorAsserts.java
│ │ │ │ ├── FakeAdaptiveDataSet.java
│ │ │ │ ├── FakeAdaptiveMediaPeriod.java
│ │ │ │ ├── FakeAdaptiveMediaSource.java
│ │ │ │ ├── FakeChunkSource.java
│ │ │ │ ├── FakeClock.java
│ │ │ │ ├── FakeDataSet.java
│ │ │ │ ├── FakeDataSource.java
│ │ │ │ ├── FakeExtractorInput.java
│ │ │ │ ├── FakeExtractorOutput.java
│ │ │ │ ├── FakeMediaPeriod.java
│ │ │ │ ├── FakeMediaSource.java
│ │ │ │ ├── FakeRenderer.java
│ │ │ │ ├── FakeSampleStream.java
│ │ │ │ ├── FakeTimeline.java
│ │ │ │ ├── FakeTrackOutput.java
│ │ │ │ ├── HostActivity.java
│ │ │ │ ├── LogcatMetricsLogger.java
│ │ │ │ ├── MetricsLogger.java
│ │ │ │ └── TestUtil.java
│ │ │ └── res/
│ │ │ └── layout/
│ │ │ └── exo_testutils_host_activity.xml
│ │ └── test/
│ │ ├── AndroidManifest.xml
│ │ └── java/
│ │ └── com/
│ │ └── google/
│ │ └── android/
│ │ └── exoplayer2/
│ │ └── testutil/
│ │ ├── FakeAdaptiveDataSetTest.java
│ │ ├── FakeClockTest.java
│ │ ├── FakeDataSetTest.java
│ │ └── FakeDataSourceTest.java
│ └── testutils_robolectric/
│ ├── build.gradle
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ └── java/
│ └── com/
│ └── google/
│ └── android/
│ └── exoplayer2/
│ └── testutil/
│ ├── CacheAsserts.java
│ ├── DefaultRenderersFactoryAsserts.java
│ ├── FakeMediaChunk.java
│ ├── FakeMediaChunkIterator.java
│ ├── FakeMediaClockRenderer.java
│ ├── FakeShuffleOrder.java
│ ├── FakeTrackSelection.java
│ ├── FakeTrackSelector.java
│ ├── MediaPeriodAsserts.java
│ ├── MediaSourceTestRunner.java
│ ├── OggTestData.java
│ ├── RobolectricUtil.java
│ ├── StubExoPlayer.java
│ ├── TestDownloadManagerListener.java
│ └── TimelineAsserts.java
├── fastlane/
│ └── metadata/
│ └── android/
│ └── en-US/
│ ├── full_description.txt
│ └── short_description.txt
├── filepicker-lib/
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── arte/
│ │ └── programar/
│ │ └── materialfile/
│ │ ├── MaterialFilePicker.java
│ │ ├── filter/
│ │ │ ├── CompositeFilter.java
│ │ │ ├── FileFilter.java
│ │ │ ├── HiddenFilter.java
│ │ │ └── PatternFilter.java
│ │ ├── ui/
│ │ │ ├── DirectoryAdapter.java
│ │ │ ├── DirectoryFragment.java
│ │ │ ├── FilePickerActivity.java
│ │ │ ├── OnItemClickListener.java
│ │ │ └── ThrottleClickListener.java
│ │ ├── utils/
│ │ │ ├── FileComparator.java
│ │ │ ├── FileTypeUtils.java
│ │ │ └── FileUtils.java
│ │ └── widget/
│ │ └── EmptyRecyclerView.java
│ └── res/
│ ├── drawable/
│ │ ├── bg_clickable.xml
│ │ ├── ic_app_apk.xml
│ │ ├── ic_app_certificate.xml
│ │ ├── ic_app_compress.xml
│ │ ├── ic_app_database.xml
│ │ ├── ic_app_directory.xml
│ │ ├── ic_app_document.xml
│ │ ├── ic_app_drawing.xml
│ │ ├── ic_app_file.xml
│ │ ├── ic_app_image.xml
│ │ ├── ic_app_json.xml
│ │ ├── ic_app_music.xml
│ │ ├── ic_app_pdf.xml
│ │ ├── ic_app_presentation.xml
│ │ ├── ic_app_spreadsheet.xml
│ │ ├── ic_app_video.xml
│ │ └── ic_close.xml
│ ├── drawable-night/
│ │ └── ic_close.xml
│ ├── drawable-v21/
│ │ └── bg_clickable.xml
│ ├── layout/
│ │ ├── activity_file_picker.xml
│ │ ├── fragment_directory.xml
│ │ └── item_file.xml
│ ├── values/
│ │ ├── attr.xml
│ │ ├── colors.xml
│ │ ├── dimen.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ ├── values-cs/
│ │ └── strings.xml
│ ├── values-de/
│ │ └── strings.xml
│ ├── values-es/
│ │ └── strings.xml
│ ├── values-night/
│ │ ├── colors.xml
│ │ └── styles.xml
│ ├── values-night-v21/
│ │ └── styles.xml
│ ├── values-night-v23/
│ │ └── styles.xml
│ ├── values-night-v27/
│ │ └── styles.xml
│ ├── values-night-v29/
│ │ └── styles.xml
│ ├── values-ru/
│ │ └── strings.xml
│ ├── values-sk/
│ │ └── strings.xml
│ ├── values-v19/
│ │ └── styles.xml
│ ├── values-v21/
│ │ └── styles.xml
│ ├── values-v23/
│ │ └── styles.xml
│ ├── values-v27/
│ │ └── styles.xml
│ ├── values-v29/
│ │ └── styles.xml
│ └── values-zh/
│ └── strings.xml
├── fragment-1.1.0/
│ ├── .gitignore
│ ├── LICENSE
│ ├── build.gradle
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ └── java/
│ └── androidx/
│ └── fragment/
│ └── app/
│ ├── BackStackRecord.java
│ ├── BackStackState.java
│ ├── DialogFragment.java
│ ├── Fragment.java
│ ├── FragmentActivity.java
│ ├── FragmentContainer.java
│ ├── FragmentController.java
│ ├── FragmentFactory.java
│ ├── FragmentHostCallback.java
│ ├── FragmentManager.java
│ ├── FragmentManagerImpl.java
│ ├── FragmentManagerNonConfig.java
│ ├── FragmentManagerState.java
│ ├── FragmentManagerViewModel.java
│ ├── FragmentPagerAdapter.java
│ ├── FragmentState.java
│ ├── FragmentStatePagerAdapter.java
│ ├── FragmentTabHost.java
│ ├── FragmentTransaction.java
│ ├── FragmentTransition.java
│ ├── FragmentTransitionCompat21.java
│ ├── FragmentTransitionImpl.java
│ ├── FragmentViewLifecycleOwner.java
│ ├── ListFragment.java
│ └── SuperNotCalledException.java
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── leanback-1.0.0/
│ ├── .gitignore
│ ├── LICENSE
│ ├── build.gradle
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── androidx/
│ │ └── leanback/
│ │ ├── animation/
│ │ │ ├── LogAccelerateInterpolator.java
│ │ │ └── LogDecelerateInterpolator.java
│ │ ├── app/
│ │ │ ├── BackgroundFragment.java
│ │ │ ├── BackgroundManager.java
│ │ │ ├── BaseFragment.java
│ │ │ ├── BaseRowFragment.java
│ │ │ ├── BaseRowSupportFragment.java
│ │ │ ├── BaseSupportFragment.java
│ │ │ ├── BrandedFragment.java
│ │ │ ├── BrandedSupportFragment.java
│ │ │ ├── BrowseFragment.java
│ │ │ ├── BrowseSupportFragment.java
│ │ │ ├── DetailsBackgroundVideoHelper.java
│ │ │ ├── DetailsFragment.java
│ │ │ ├── DetailsFragmentBackgroundController.java
│ │ │ ├── DetailsSupportFragment.java
│ │ │ ├── DetailsSupportFragmentBackgroundController.java
│ │ │ ├── ErrorFragment.java
│ │ │ ├── ErrorSupportFragment.java
│ │ │ ├── FragmentUtil.java
│ │ │ ├── GuidedStepFragment.java
│ │ │ ├── GuidedStepRootLayout.java
│ │ │ ├── GuidedStepSupportFragment.java
│ │ │ ├── HeadersFragment.java
│ │ │ ├── HeadersSupportFragment.java
│ │ │ ├── ListRowDataAdapter.java
│ │ │ ├── OnboardingFragment.java
│ │ │ ├── OnboardingSupportFragment.java
│ │ │ ├── PermissionHelper.java
│ │ │ ├── PlaybackFragment.java
│ │ │ ├── PlaybackFragmentGlueHost.java
│ │ │ ├── PlaybackSupportFragment.java
│ │ │ ├── PlaybackSupportFragmentGlueHost.java
│ │ │ ├── ProgressBarManager.java
│ │ │ ├── RowsFragment.java
│ │ │ ├── RowsSupportFragment.java
│ │ │ ├── SearchFragment.java
│ │ │ ├── SearchSupportFragment.java
│ │ │ ├── VerticalGridFragment.java
│ │ │ ├── VerticalGridSupportFragment.java
│ │ │ ├── VideoFragment.java
│ │ │ ├── VideoFragmentGlueHost.java
│ │ │ ├── VideoSupportFragment.java
│ │ │ ├── VideoSupportFragmentGlueHost.java
│ │ │ └── package-info.java
│ │ ├── database/
│ │ │ └── CursorMapper.java
│ │ ├── graphics/
│ │ │ ├── BoundsRule.java
│ │ │ ├── ColorFilterCache.java
│ │ │ ├── ColorFilterDimmer.java
│ │ │ ├── ColorOverlayDimmer.java
│ │ │ ├── CompositeDrawable.java
│ │ │ └── FitWidthBitmapDrawable.java
│ │ ├── media/
│ │ │ ├── MediaControllerAdapter.java
│ │ │ ├── MediaControllerGlue.java
│ │ │ ├── MediaPlayerAdapter.java
│ │ │ ├── MediaPlayerGlue.java
│ │ │ ├── PlaybackBannerControlGlue.java
│ │ │ ├── PlaybackBaseControlGlue.java
│ │ │ ├── PlaybackControlGlue.java
│ │ │ ├── PlaybackGlue.java
│ │ │ ├── PlaybackGlueHost.java
│ │ │ ├── PlaybackTransportControlGlue.java
│ │ │ ├── PlayerAdapter.java
│ │ │ └── SurfaceHolderGlueHost.java
│ │ ├── package-info.java
│ │ ├── system/
│ │ │ └── Settings.java
│ │ ├── transition/
│ │ │ ├── CustomChangeBounds.java
│ │ │ ├── FadeAndShortSlide.java
│ │ │ ├── LeanbackTransitionHelper.java
│ │ │ ├── ParallaxTransition.java
│ │ │ ├── Scale.java
│ │ │ ├── SlideKitkat.java
│ │ │ ├── SlideNoPropagation.java
│ │ │ ├── TransitionEpicenterCallback.java
│ │ │ ├── TransitionHelper.java
│ │ │ ├── TransitionListener.java
│ │ │ └── TranslationAnimationCreator.java
│ │ ├── util/
│ │ │ ├── MathUtil.java
│ │ │ └── StateMachine.java
│ │ └── widget/
│ │ ├── AbstractDetailsDescriptionPresenter.java
│ │ ├── AbstractMediaItemPresenter.java
│ │ ├── AbstractMediaListHeaderPresenter.java
│ │ ├── Action.java
│ │ ├── ActionPresenterSelector.java
│ │ ├── ArrayObjectAdapter.java
│ │ ├── BackgroundHelper.java
│ │ ├── BaseCardView.java
│ │ ├── BaseGridView.java
│ │ ├── BaseOnItemViewClickedListener.java
│ │ ├── BaseOnItemViewSelectedListener.java
│ │ ├── BrowseFrameLayout.java
│ │ ├── BrowseRowsFrameLayout.java
│ │ ├── CheckableImageView.java
│ │ ├── ClassPresenterSelector.java
│ │ ├── ControlBar.java
│ │ ├── ControlBarPresenter.java
│ │ ├── ControlButtonPresenterSelector.java
│ │ ├── CursorObjectAdapter.java
│ │ ├── DetailsOverviewLogoPresenter.java
│ │ ├── DetailsOverviewRow.java
│ │ ├── DetailsOverviewRowPresenter.java
│ │ ├── DetailsOverviewSharedElementHelper.java
│ │ ├── DetailsParallax.java
│ │ ├── DetailsParallaxDrawable.java
│ │ ├── DiffCallback.java
│ │ ├── DividerPresenter.java
│ │ ├── DividerRow.java
│ │ ├── FacetProvider.java
│ │ ├── FacetProviderAdapter.java
│ │ ├── FocusHighlight.java
│ │ ├── FocusHighlightHandler.java
│ │ ├── FocusHighlightHelper.java
│ │ ├── ForegroundHelper.java
│ │ ├── FragmentAnimationProvider.java
│ │ ├── FullWidthDetailsOverviewRowPresenter.java
│ │ ├── FullWidthDetailsOverviewSharedElementHelper.java
│ │ ├── Grid.java
│ │ ├── GridLayoutManager.java
│ │ ├── GuidanceStylingRelativeLayout.java
│ │ ├── GuidanceStylist.java
│ │ ├── GuidedAction.java
│ │ ├── GuidedActionAdapter.java
│ │ ├── GuidedActionAdapterGroup.java
│ │ ├── GuidedActionAutofillSupport.java
│ │ ├── GuidedActionDiffCallback.java
│ │ ├── GuidedActionEditText.java
│ │ ├── GuidedActionItemContainer.java
│ │ ├── GuidedActionsRelativeLayout.java
│ │ ├── GuidedActionsStylist.java
│ │ ├── GuidedDatePickerAction.java
│ │ ├── HeaderItem.java
│ │ ├── HorizontalGridView.java
│ │ ├── HorizontalHoverCardSwitcher.java
│ │ ├── ImageCardView.java
│ │ ├── ImeKeyMonitor.java
│ │ ├── InvisibleRowPresenter.java
│ │ ├── ItemAlignment.java
│ │ ├── ItemAlignmentFacet.java
│ │ ├── ItemAlignmentFacetHelper.java
│ │ ├── ItemBridgeAdapter.java
│ │ ├── ItemBridgeAdapterShadowOverlayWrapper.java
│ │ ├── ListRow.java
│ │ ├── ListRowHoverCardView.java
│ │ ├── ListRowPresenter.java
│ │ ├── ListRowView.java
│ │ ├── MediaItemActionPresenter.java
│ │ ├── MediaNowPlayingView.java
│ │ ├── MediaRowFocusView.java
│ │ ├── MultiActionsProvider.java
│ │ ├── NonOverlappingFrameLayout.java
│ │ ├── NonOverlappingLinearLayout.java
│ │ ├── NonOverlappingLinearLayoutWithForeground.java
│ │ ├── NonOverlappingRelativeLayout.java
│ │ ├── NonOverlappingView.java
│ │ ├── ObjectAdapter.java
│ │ ├── OnActionClickedListener.java
│ │ ├── OnChildLaidOutListener.java
│ │ ├── OnChildSelectedListener.java
│ │ ├── OnChildViewHolderSelectedListener.java
│ │ ├── OnItemViewClickedListener.java
│ │ ├── OnItemViewSelectedListener.java
│ │ ├── PageRow.java
│ │ ├── PagingIndicator.java
│ │ ├── Parallax.java
│ │ ├── ParallaxEffect.java
│ │ ├── ParallaxTarget.java
│ │ ├── PersistentFocusWrapper.java
│ │ ├── PlaybackControlsPresenter.java
│ │ ├── PlaybackControlsRow.java
│ │ ├── PlaybackControlsRowPresenter.java
│ │ ├── PlaybackControlsRowView.java
│ │ ├── PlaybackRowPresenter.java
│ │ ├── PlaybackSeekDataProvider.java
│ │ ├── PlaybackSeekUi.java
│ │ ├── PlaybackTransportRowPresenter.java
│ │ ├── PlaybackTransportRowView.java
│ │ ├── Presenter.java
│ │ ├── PresenterSelector.java
│ │ ├── PresenterSwitcher.java
│ │ ├── RecyclerViewParallax.java
│ │ ├── ResizingTextView.java
│ │ ├── RoundedRectHelper.java
│ │ ├── RoundedRectHelperApi21.java
│ │ ├── Row.java
│ │ ├── RowContainerView.java
│ │ ├── RowHeaderPresenter.java
│ │ ├── RowHeaderView.java
│ │ ├── RowPresenter.java
│ │ ├── ScaleFrameLayout.java
│ │ ├── SearchBar.java
│ │ ├── SearchEditText.java
│ │ ├── SearchOrbView.java
│ │ ├── SectionRow.java
│ │ ├── SeekBar.java
│ │ ├── ShadowHelper.java
│ │ ├── ShadowHelperApi21.java
│ │ ├── ShadowOverlayContainer.java
│ │ ├── ShadowOverlayHelper.java
│ │ ├── SinglePresenterSelector.java
│ │ ├── SingleRow.java
│ │ ├── SparseArrayObjectAdapter.java
│ │ ├── SpeechOrbView.java
│ │ ├── SpeechRecognitionCallback.java
│ │ ├── StaggeredGrid.java
│ │ ├── StaggeredGridDefault.java
│ │ ├── StaticShadowHelper.java
│ │ ├── StreamingTextView.java
│ │ ├── ThumbsBar.java
│ │ ├── TitleHelper.java
│ │ ├── TitleView.java
│ │ ├── TitleViewAdapter.java
│ │ ├── Util.java
│ │ ├── VerticalGridPresenter.java
│ │ ├── VerticalGridView.java
│ │ ├── VideoSurfaceView.java
│ │ ├── ViewHolderTask.java
│ │ ├── ViewsStateBundle.java
│ │ ├── Visibility.java
│ │ ├── WindowAlignment.java
│ │ ├── package-info.java
│ │ └── picker/
│ │ ├── DatePicker.java
│ │ ├── Picker.java
│ │ ├── PickerColumn.java
│ │ ├── PickerUtility.java
│ │ └── TimePicker.java
│ └── res/
│ ├── anim/
│ │ ├── lb_decelerator_2.xml
│ │ └── lb_decelerator_4.xml
│ ├── animator/
│ │ ├── lb_guidedactions_item_pressed.xml
│ │ ├── lb_guidedactions_item_unpressed.xml
│ │ ├── lb_guidedstep_slide_down.xml
│ │ ├── lb_guidedstep_slide_up.xml
│ │ ├── lb_onboarding_description_enter.xml
│ │ ├── lb_onboarding_logo_enter.xml
│ │ ├── lb_onboarding_logo_exit.xml
│ │ ├── lb_onboarding_page_indicator_enter.xml
│ │ ├── lb_onboarding_page_indicator_fade_in.xml
│ │ ├── lb_onboarding_page_indicator_fade_out.xml
│ │ ├── lb_onboarding_start_button_fade_in.xml
│ │ ├── lb_onboarding_start_button_fade_out.xml
│ │ ├── lb_onboarding_title_enter.xml
│ │ ├── lb_playback_bg_fade_in.xml
│ │ ├── lb_playback_bg_fade_out.xml
│ │ ├── lb_playback_controls_fade_in.xml
│ │ ├── lb_playback_controls_fade_out.xml
│ │ ├── lb_playback_description_fade_in.xml
│ │ ├── lb_playback_description_fade_out.xml
│ │ ├── lb_playback_rows_fade_in.xml
│ │ └── lb_playback_rows_fade_out.xml
│ ├── animator-v21/
│ │ ├── lb_onboarding_description_enter.xml
│ │ ├── lb_onboarding_logo_enter.xml
│ │ ├── lb_onboarding_logo_exit.xml
│ │ ├── lb_onboarding_page_indicator_enter.xml
│ │ ├── lb_onboarding_title_enter.xml
│ │ ├── lb_playback_bg_fade_in.xml
│ │ ├── lb_playback_bg_fade_out.xml
│ │ └── lb_playback_description_fade_out.xml
│ ├── drawable/
│ │ ├── lb_background.xml
│ │ ├── lb_card_foreground.xml
│ │ ├── lb_control_button_primary.xml
│ │ ├── lb_control_button_secondary.xml
│ │ ├── lb_headers_right_fading.xml
│ │ ├── lb_onboarding_start_button_background.xml
│ │ ├── lb_playback_now_playing_bar.xml
│ │ ├── lb_playback_progress_bar.xml
│ │ ├── lb_search_orb.xml
│ │ └── lb_speech_orb.xml
│ ├── drawable-v21/
│ │ ├── lb_action_bg.xml
│ │ ├── lb_card_foreground.xml
│ │ ├── lb_control_button_primary.xml
│ │ ├── lb_control_button_secondary.xml
│ │ └── lb_selectable_item_rounded_rect.xml
│ ├── layout/
│ │ ├── lb_action_1_line.xml
│ │ ├── lb_action_2_lines.xml
│ │ ├── lb_background_window.xml
│ │ ├── lb_browse_fragment.xml
│ │ ├── lb_browse_title.xml
│ │ ├── lb_control_bar.xml
│ │ ├── lb_control_button_primary.xml
│ │ ├── lb_control_button_secondary.xml
│ │ ├── lb_details_description.xml
│ │ ├── lb_details_fragment.xml
│ │ ├── lb_details_overview.xml
│ │ ├── lb_divider.xml
│ │ ├── lb_error_fragment.xml
│ │ ├── lb_fullwidth_details_overview.xml
│ │ ├── lb_fullwidth_details_overview_logo.xml
│ │ ├── lb_guidance.xml
│ │ ├── lb_guidedactions.xml
│ │ ├── lb_guidedactions_datepicker_item.xml
│ │ ├── lb_guidedactions_item.xml
│ │ ├── lb_guidedbuttonactions.xml
│ │ ├── lb_guidedstep_background.xml
│ │ ├── lb_guidedstep_fragment.xml
│ │ ├── lb_header.xml
│ │ ├── lb_headers_fragment.xml
│ │ ├── lb_image_card_view.xml
│ │ ├── lb_image_card_view_themed_badge_left.xml
│ │ ├── lb_image_card_view_themed_badge_right.xml
│ │ ├── lb_image_card_view_themed_content.xml
│ │ ├── lb_image_card_view_themed_title.xml
│ │ ├── lb_list_row.xml
│ │ ├── lb_list_row_hovercard.xml
│ │ ├── lb_media_item_number_view_flipper.xml
│ │ ├── lb_media_list_header.xml
│ │ ├── lb_onboarding_fragment.xml
│ │ ├── lb_picker.xml
│ │ ├── lb_picker_column.xml
│ │ ├── lb_picker_item.xml
│ │ ├── lb_picker_separator.xml
│ │ ├── lb_playback_controls.xml
│ │ ├── lb_playback_controls_row.xml
│ │ ├── lb_playback_fragment.xml
│ │ ├── lb_playback_now_playing_bars.xml
│ │ ├── lb_playback_transport_controls.xml
│ │ ├── lb_playback_transport_controls_row.xml
│ │ ├── lb_row_container.xml
│ │ ├── lb_row_header.xml
│ │ ├── lb_row_media_item.xml
│ │ ├── lb_row_media_item_action.xml
│ │ ├── lb_rows_fragment.xml
│ │ ├── lb_search_bar.xml
│ │ ├── lb_search_fragment.xml
│ │ ├── lb_search_orb.xml
│ │ ├── lb_section_header.xml
│ │ ├── lb_shadow.xml
│ │ ├── lb_speech_orb.xml
│ │ ├── lb_title_view.xml
│ │ ├── lb_vertical_grid.xml
│ │ ├── lb_vertical_grid_fragment.xml
│ │ ├── lb_video_surface.xml
│ │ └── video_surface_fragment.xml
│ ├── raw/
│ │ ├── lb_voice_failure.ogg
│ │ ├── lb_voice_no_input.ogg
│ │ ├── lb_voice_open.ogg
│ │ └── lb_voice_success.ogg
│ ├── transition-v19/
│ │ ├── lb_browse_headers_in.xml
│ │ └── lb_browse_headers_out.xml
│ ├── transition-v21/
│ │ ├── lb_browse_enter_transition.xml
│ │ ├── lb_browse_entrance_transition.xml
│ │ ├── lb_browse_headers_in.xml
│ │ ├── lb_browse_headers_out.xml
│ │ ├── lb_browse_return_transition.xml
│ │ ├── lb_details_enter_transition.xml
│ │ ├── lb_details_return_transition.xml
│ │ ├── lb_enter_transition.xml
│ │ ├── lb_guidedstep_activity_enter.xml
│ │ ├── lb_guidedstep_activity_enter_bottom.xml
│ │ ├── lb_return_transition.xml
│ │ ├── lb_shared_element_enter_transition.xml
│ │ ├── lb_shared_element_return_transition.xml
│ │ ├── lb_title_in.xml
│ │ ├── lb_title_out.xml
│ │ ├── lb_vertical_grid_enter_transition.xml
│ │ ├── lb_vertical_grid_entrance_transition.xml
│ │ └── lb_vertical_grid_return_transition.xml
│ ├── values/
│ │ └── values.xml
│ ├── values-af/
│ │ └── values-af.xml
│ ├── values-am/
│ │ └── values-am.xml
│ ├── values-ar/
│ │ └── values-ar.xml
│ ├── values-as/
│ │ └── values-as.xml
│ ├── values-az/
│ │ └── values-az.xml
│ ├── values-b+sr+Latn/
│ │ └── values-b+sr+Latn.xml
│ ├── values-be/
│ │ └── values-be.xml
│ ├── values-bg/
│ │ └── values-bg.xml
│ ├── values-bn/
│ │ └── values-bn.xml
│ ├── values-bs/
│ │ └── values-bs.xml
│ ├── values-ca/
│ │ └── values-ca.xml
│ ├── values-cs/
│ │ └── values-cs.xml
│ ├── values-da/
│ │ └── values-da.xml
│ ├── values-de/
│ │ └── values-de.xml
│ ├── values-el/
│ │ └── values-el.xml
│ ├── values-en-rAU/
│ │ └── values-en-rAU.xml
│ ├── values-en-rCA/
│ │ └── values-en-rCA.xml
│ ├── values-en-rGB/
│ │ └── values-en-rGB.xml
│ ├── values-en-rIN/
│ │ └── values-en-rIN.xml
│ ├── values-en-rXC/
│ │ └── values-en-rXC.xml
│ ├── values-es/
│ │ └── values-es.xml
│ ├── values-es-rUS/
│ │ └── values-es-rUS.xml
│ ├── values-et/
│ │ └── values-et.xml
│ ├── values-eu/
│ │ └── values-eu.xml
│ ├── values-fa/
│ │ └── values-fa.xml
│ ├── values-fi/
│ │ └── values-fi.xml
│ ├── values-fr/
│ │ └── values-fr.xml
│ ├── values-fr-rCA/
│ │ └── values-fr-rCA.xml
│ ├── values-gl/
│ │ └── values-gl.xml
│ ├── values-gu/
│ │ └── values-gu.xml
│ ├── values-hi/
│ │ └── values-hi.xml
│ ├── values-hr/
│ │ └── values-hr.xml
│ ├── values-hu/
│ │ └── values-hu.xml
│ ├── values-hy/
│ │ └── values-hy.xml
│ ├── values-in/
│ │ └── values-in.xml
│ ├── values-is/
│ │ └── values-is.xml
│ ├── values-it/
│ │ └── values-it.xml
│ ├── values-iw/
│ │ └── values-iw.xml
│ ├── values-ja/
│ │ └── values-ja.xml
│ ├── values-ka/
│ │ └── values-ka.xml
│ ├── values-kk/
│ │ └── values-kk.xml
│ ├── values-km/
│ │ └── values-km.xml
│ ├── values-kn/
│ │ └── values-kn.xml
│ ├── values-ko/
│ │ └── values-ko.xml
│ ├── values-ky/
│ │ └── values-ky.xml
│ ├── values-ldrtl-v17/
│ │ └── values-ldrtl-v17.xml
│ ├── values-lo/
│ │ └── values-lo.xml
│ ├── values-lt/
│ │ └── values-lt.xml
│ ├── values-lv/
│ │ └── values-lv.xml
│ ├── values-mk/
│ │ └── values-mk.xml
│ ├── values-ml/
│ │ └── values-ml.xml
│ ├── values-mn/
│ │ └── values-mn.xml
│ ├── values-mr/
│ │ └── values-mr.xml
│ ├── values-ms/
│ │ └── values-ms.xml
│ ├── values-my/
│ │ └── values-my.xml
│ ├── values-nb/
│ │ └── values-nb.xml
│ ├── values-ne/
│ │ └── values-ne.xml
│ ├── values-nl/
│ │ └── values-nl.xml
│ ├── values-or/
│ │ └── values-or.xml
│ ├── values-pa/
│ │ └── values-pa.xml
│ ├── values-pl/
│ │ └── values-pl.xml
│ ├── values-pt/
│ │ └── values-pt.xml
│ ├── values-pt-rBR/
│ │ └── values-pt-rBR.xml
│ ├── values-pt-rPT/
│ │ └── values-pt-rPT.xml
│ ├── values-ro/
│ │ └── values-ro.xml
│ ├── values-ru/
│ │ └── values-ru.xml
│ ├── values-si/
│ │ └── values-si.xml
│ ├── values-sk/
│ │ └── values-sk.xml
│ ├── values-sl/
│ │ └── values-sl.xml
│ ├── values-sq/
│ │ └── values-sq.xml
│ ├── values-sr/
│ │ └── values-sr.xml
│ ├── values-sv/
│ │ └── values-sv.xml
│ ├── values-sw/
│ │ └── values-sw.xml
│ ├── values-ta/
│ │ └── values-ta.xml
│ ├── values-te/
│ │ └── values-te.xml
│ ├── values-th/
│ │ └── values-th.xml
│ ├── values-tl/
│ │ └── values-tl.xml
│ ├── values-tr/
│ │ └── values-tr.xml
│ ├── values-uk/
│ │ └── values-uk.xml
│ ├── values-ur/
│ │ └── values-ur.xml
│ ├── values-uz/
│ │ └── values-uz.xml
│ ├── values-v18/
│ │ └── values-v18.xml
│ ├── values-v19/
│ │ └── values-v19.xml
│ ├── values-v21/
│ │ └── values-v21.xml
│ ├── values-v22/
│ │ └── values-v22.xml
│ ├── values-vi/
│ │ └── values-vi.xml
│ ├── values-zh-rCN/
│ │ └── values-zh-rCN.xml
│ ├── values-zh-rHK/
│ │ └── values-zh-rHK.xml
│ ├── values-zh-rTW/
│ │ └── values-zh-rTW.xml
│ └── values-zu/
│ └── values-zu.xml
├── leanbackassistant/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── liskovsoft/
│ │ │ └── leanbackassistant/
│ │ │ ├── channels/
│ │ │ │ ├── ChannelsProvider.java
│ │ │ │ ├── UpdateChannelsJobService.java
│ │ │ │ ├── UpdateChannelsReceiver.java
│ │ │ │ ├── UpdateChannelsTask.java
│ │ │ │ └── UpdateChannelsWorker.java
│ │ │ ├── media/
│ │ │ │ ├── Clip.java
│ │ │ │ ├── ClipService.java
│ │ │ │ ├── ClipServiceCached.java
│ │ │ │ ├── Playlist.java
│ │ │ │ └── scheduler/
│ │ │ │ └── ClipData.java
│ │ │ ├── recommendations/
│ │ │ │ ├── RecommendationBuilder.java
│ │ │ │ └── RecommendationsProvider.java
│ │ │ ├── search/
│ │ │ │ ├── MockDatabase.java
│ │ │ │ ├── SearchableActivity.java
│ │ │ │ └── VideoContentProvider.java
│ │ │ └── utils/
│ │ │ └── AppUtil.java
│ │ └── res/
│ │ ├── values/
│ │ │ ├── colors.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ ├── values-es/
│ │ │ └── strings.xml
│ │ ├── values-ru/
│ │ │ └── strings.xml
│ │ ├── values-tr/
│ │ │ └── strings.xml
│ │ ├── values-uk/
│ │ │ └── strings.xml
│ │ └── xml/
│ │ └── searchable.xml
│ ├── stbeta/
│ │ ├── AndroidManifest.xml
│ │ └── res/
│ │ ├── values/
│ │ │ └── strings.xml
│ │ └── xml/
│ │ └── searchable.xml
│ ├── stfdroid/
│ │ ├── AndroidManifest.xml
│ │ └── res/
│ │ ├── values/
│ │ │ └── strings.xml
│ │ └── xml/
│ │ └── searchable.xml
│ └── ststable/
│ ├── AndroidManifest.xml
│ └── res/
│ ├── values/
│ │ └── strings.xml
│ └── xml/
│ └── searchable.xml
├── settings.gradle
├── slidableactivity/
│ ├── .gitignore
│ ├── LICENSE.md
│ ├── README.md
│ ├── build.gradle
│ ├── gradle.properties
│ └── src/
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── r0adkll/
│ │ │ └── slidr/
│ │ │ ├── ColorPanelSlideListener.java
│ │ │ ├── ConfigPanelSlideListener.java
│ │ │ ├── FragmentPanelSlideListener.java
│ │ │ ├── Slidr.java
│ │ │ ├── model/
│ │ │ │ ├── SlidrConfig.java
│ │ │ │ ├── SlidrInterface.java
│ │ │ │ ├── SlidrListener.java
│ │ │ │ ├── SlidrListenerAdapter.java
│ │ │ │ └── SlidrPosition.java
│ │ │ ├── util/
│ │ │ │ └── ViewDragHelper.java
│ │ │ └── widget/
│ │ │ ├── ScrimRenderer.java
│ │ │ └── SliderPanel.java
│ │ └── res/
│ │ └── values/
│ │ └── ids.xml
│ └── test/
│ └── java/
│ └── com/
│ └── r0adkll/
│ └── slidr/
│ └── widget/
│ ├── ScrimRendererTest.java
│ └── SliderPanelTest.java
└── smarttubetv/
├── build.gradle
├── google-services.json
├── multidex-keep.pro
├── proguard-rules.pro
└── src/
├── main/
│ ├── AndroidManifest.xml
│ ├── assets/
│ │ └── common.properties
│ ├── java/
│ │ └── com/
│ │ └── liskovsoft/
│ │ └── smartyoutubetv2/
│ │ └── tv/
│ │ ├── adapter/
│ │ │ ├── DeferredVideoGroupObjectAdapter.java
│ │ │ ├── HeaderVideoGroupObjectAdapter.java
│ │ │ ├── VideoGroupObjectAdapter.java
│ │ │ └── vineyard/
│ │ │ ├── PaginationAdapter.java
│ │ │ └── TagAdapter.java
│ │ ├── launchers/
│ │ │ ├── ChannelsLauncherActivity.java
│ │ │ ├── GamesLauncherActivity.java
│ │ │ ├── HistoryLauncherActivity.java
│ │ │ ├── HomeLauncherActivity.java
│ │ │ ├── MusicLauncherActivity.java
│ │ │ ├── NewsLauncherActivity.java
│ │ │ ├── PlaylistsLauncherActivity.java
│ │ │ ├── SearchLauncherActivity.java
│ │ │ └── SubscriptionsLauncherActivity.java
│ │ ├── presenter/
│ │ │ ├── ChannelCardPresenter.java
│ │ │ ├── ChannelHeaderPresenter.java
│ │ │ ├── CustomListRowPresenter.java
│ │ │ ├── CustomVerticalGridPresenter.java
│ │ │ ├── DetailsDescriptionPresenter.java
│ │ │ ├── GridItemPresenter.java
│ │ │ ├── IconHeaderItemPresenter.java
│ │ │ ├── SearchFieldPresenter.java
│ │ │ ├── SettingsCardPresenter.java
│ │ │ ├── ShortsCardPresenter.java
│ │ │ ├── TinyCardPresenter.java
│ │ │ ├── VideoCardPresenter.java
│ │ │ ├── base/
│ │ │ │ ├── LongClickPresenter.java
│ │ │ │ └── OnItemLongPressedListener.java
│ │ │ └── vineyard/
│ │ │ ├── IconItemPresenter.java
│ │ │ ├── LoadingPresenter.java
│ │ │ └── TagPresenter.java
│ │ ├── ui/
│ │ │ ├── adddevice/
│ │ │ │ ├── AddDeviceActivity.java
│ │ │ │ └── AddDeviceFragment.java
│ │ │ ├── browse/
│ │ │ │ ├── BrowseActivity.java
│ │ │ │ ├── BrowseFragment.java
│ │ │ │ ├── BrowseSectionFragmentFactory.java
│ │ │ │ ├── CategoryFragmentFactory.java.old
│ │ │ │ ├── SectionHeaderItem.java
│ │ │ │ ├── dialog/
│ │ │ │ │ └── ErrorDialogFragment.java
│ │ │ │ ├── interfaces/
│ │ │ │ │ ├── Section.java
│ │ │ │ │ ├── SettingsSection.java
│ │ │ │ │ └── VideoSection.java
│ │ │ │ ├── settings/
│ │ │ │ │ └── SettingsGridFragment.java
│ │ │ │ └── video/
│ │ │ │ ├── GridFragmentHelper.java
│ │ │ │ ├── MultiVideoGridFragment.java
│ │ │ │ ├── MultipleRowsFragment.java
│ │ │ │ ├── ShortsGridFragment.java
│ │ │ │ ├── VideoGridFragment.java
│ │ │ │ └── VideoRowsFragment.java
│ │ │ ├── channel/
│ │ │ │ ├── ChannelActivity.java
│ │ │ │ └── ChannelFragment.java
│ │ │ ├── channeluploads/
│ │ │ │ ├── ChannelUploadsActivity.java
│ │ │ │ └── ChannelUploadsFragment.java
│ │ │ ├── common/
│ │ │ │ ├── DisplayUtils.java
│ │ │ │ ├── LeanbackActivity.java
│ │ │ │ ├── UriBackgroundManager.java
│ │ │ │ └── keyhandler/
│ │ │ │ ├── DoubleBackManager.java
│ │ │ │ ├── DoubleBackManager2.java
│ │ │ │ └── LongClickManager.java
│ │ │ ├── dialogs/
│ │ │ │ ├── AppDialogActivity.java
│ │ │ │ ├── AppDialogFragment.java
│ │ │ │ ├── AppPreferenceManager.java
│ │ │ │ └── other/
│ │ │ │ ├── ChatPreference.java
│ │ │ │ ├── ChatPreferenceDialogFragment.java
│ │ │ │ ├── CommentsPreference.java
│ │ │ │ ├── CommentsPreferenceDialogFragment.java
│ │ │ │ ├── RadioListPreferenceDialogFragment.java
│ │ │ │ ├── StringListPreference.java
│ │ │ │ └── StringListPreferenceDialogFragment.java
│ │ │ ├── main/
│ │ │ │ ├── MainApplication.java
│ │ │ │ └── SplashActivity.java
│ │
Showing preview only (1,721K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (19867 symbols across 1253 files)
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/DebouncedOnClickListener.java
class DebouncedOnClickListener (line 14) | public abstract class DebouncedOnClickListener implements View.OnClickLi...
method onDebouncedClick (line 24) | public abstract void onDebouncedClick(View v);
method DebouncedOnClickListener (line 31) | public DebouncedOnClickListener(long minimumIntervalMillis) {
method onClick (line 36) | @Override
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/ImageLoader.java
type ImageLoader (line 26) | public interface ImageLoader {
method loadImage (line 28) | void loadImage(ImageView imageView, @Nullable String url, @Nullable Ob...
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/InputTrackingRecyclerViewAdapter.java
class InputTrackingRecyclerViewAdapter (line 10) | public abstract class InputTrackingRecyclerViewAdapter<VH extends Recycl...
method onAttachedToRecyclerView (line 14) | @Override
method tryMoveSelection (line 50) | private boolean tryMoveSelection(RecyclerView.LayoutManager lm, int di...
method getSelectedItem (line 66) | public int getSelectedItem() {
method setSelectedItem (line 70) | public void setSelectedItem(int selectedItem) {
method getRecyclerView (line 74) | public RecyclerView getRecyclerView() {
method onBindViewHolder (line 78) | @Override
method isConfirmButton (line 83) | public static boolean isConfirmButton(KeyEvent event) {
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/Style.java
class Style (line 38) | public abstract class Style {
method Style (line 44) | protected Style(Context context, AttributeSet attrs) {
method getSystemAccentColor (line 50) | protected final int getSystemAccentColor() {
method getSystemPrimaryColor (line 54) | protected final int getSystemPrimaryColor() {
method getSystemPrimaryDarkColor (line 58) | protected final int getSystemPrimaryDarkColor() {
method getSystemPrimaryTextColor (line 62) | protected final int getSystemPrimaryTextColor() {
method getSystemHintColor (line 66) | protected final int getSystemHintColor() {
method getSystemColor (line 70) | protected final int getSystemColor(@AttrRes int attr) {
method getDimension (line 81) | protected final int getDimension(@DimenRes int dimen) {
method getColor (line 85) | protected final int getColor(@ColorRes int color) {
method getDrawable (line 89) | protected final Drawable getDrawable(@DrawableRes int drawable) {
method getVectorDrawable (line 93) | protected final Drawable getVectorDrawable(@DrawableRes int drawable) {
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/ViewHolder.java
class ViewHolder (line 26) | public abstract class ViewHolder<DATA> extends RecyclerView.ViewHolder {
method onBind (line 28) | public abstract void onBind(DATA data);
method ViewHolder (line 30) | public ViewHolder(View itemView) {
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/models/IDialog.java
type IDialog (line 25) | public interface IDialog<MESSAGE extends IMessage> {
method getId (line 27) | String getId();
method getDialogPhoto (line 29) | String getDialogPhoto();
method getDialogName (line 31) | String getDialogName();
method getUsers (line 33) | List<? extends IUser> getUsers();
method getLastMessage (line 35) | MESSAGE getLastMessage();
method setLastMessage (line 37) | void setLastMessage(MESSAGE message);
method getUnreadCount (line 39) | int getUnreadCount();
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/models/IMessage.java
type IMessage (line 24) | public interface IMessage {
method getId (line 31) | String getId();
method getText (line 38) | CharSequence getText();
method getUser (line 45) | IUser getUser();
method getCreatedAt (line 52) | Date getCreatedAt();
method checkMessage (line 54) | static boolean checkMessage(IMessage message) {
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/models/IUser.java
type IUser (line 22) | public interface IUser {
method getId (line 29) | String getId();
method getName (line 36) | String getName();
method getAvatar (line 43) | String getAvatar();
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/models/MessageContentType.java
type MessageContentType (line 31) | public interface MessageContentType extends IMessage {
type Image (line 36) | interface Image extends IMessage {
method getImageUrl (line 37) | @Nullable
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/widgets/FocusFixRelativeLayout.java
class FocusFixRelativeLayout (line 10) | public class FocusFixRelativeLayout extends RelativeLayout {
method FocusFixRelativeLayout (line 11) | public FocusFixRelativeLayout(Context context) {
method FocusFixRelativeLayout (line 15) | public FocusFixRelativeLayout(Context context, AttributeSet attrs) {
method FocusFixRelativeLayout (line 19) | public FocusFixRelativeLayout(Context context, AttributeSet attrs, int...
method FocusFixRelativeLayout (line 23) | @SuppressWarnings("NewApi")
method clearFocus (line 28) | @Override
FILE: chatkit/src/main/java/com/stfalcon/chatkit/commons/widgets/WrapWidthTextView.java
class WrapWidthTextView (line 15) | public class WrapWidthTextView extends AppCompatTextView {
method WrapWidthTextView (line 16) | public WrapWidthTextView(@NonNull Context context) {
method WrapWidthTextView (line 20) | public WrapWidthTextView(@NonNull Context context, @Nullable Attribute...
method WrapWidthTextView (line 24) | public WrapWidthTextView(@NonNull Context context, @Nullable Attribute...
method onMeasure (line 28) | @Override
method getMaxLineWidth (line 41) | private float getMaxLineWidth(Layout layout) {
FILE: chatkit/src/main/java/com/stfalcon/chatkit/dialogs/DialogListStyle.java
class DialogListStyle (line 30) | @SuppressWarnings("WeakerAccess")
method parse (line 72) | static DialogListStyle parse(Context context, AttributeSet attrs) {
method DialogListStyle (line 157) | private DialogListStyle(Context context, AttributeSet attrs) {
method getDialogTitleTextColor (line 161) | protected int getDialogTitleTextColor() {
method getDialogTitleTextSize (line 165) | protected int getDialogTitleTextSize() {
method getDialogTitleTextStyle (line 169) | protected int getDialogTitleTextStyle() {
method getDialogUnreadTitleTextColor (line 173) | protected int getDialogUnreadTitleTextColor() {
method getDialogUnreadTitleTextStyle (line 177) | protected int getDialogUnreadTitleTextStyle() {
method getDialogMessageTextColor (line 181) | protected int getDialogMessageTextColor() {
method getDialogMessageTextSize (line 185) | protected int getDialogMessageTextSize() {
method getDialogMessageTextStyle (line 189) | protected int getDialogMessageTextStyle() {
method getDialogUnreadMessageTextColor (line 193) | protected int getDialogUnreadMessageTextColor() {
method getDialogUnreadMessageTextStyle (line 197) | protected int getDialogUnreadMessageTextStyle() {
method getDialogDateColor (line 201) | protected int getDialogDateColor() {
method getDialogDateSize (line 205) | protected int getDialogDateSize() {
method getDialogDateStyle (line 209) | protected int getDialogDateStyle() {
method getDialogUnreadDateColor (line 213) | protected int getDialogUnreadDateColor() {
method getDialogUnreadDateStyle (line 217) | protected int getDialogUnreadDateStyle() {
method isDialogUnreadBubbleEnabled (line 221) | protected boolean isDialogUnreadBubbleEnabled() {
method getDialogUnreadBubbleTextColor (line 225) | protected int getDialogUnreadBubbleTextColor() {
method getDialogUnreadBubbleTextSize (line 229) | protected int getDialogUnreadBubbleTextSize() {
method getDialogUnreadBubbleTextStyle (line 233) | protected int getDialogUnreadBubbleTextStyle() {
method getDialogUnreadBubbleBackgroundColor (line 237) | protected int getDialogUnreadBubbleBackgroundColor() {
method getDialogAvatarWidth (line 241) | protected int getDialogAvatarWidth() {
method getDialogAvatarHeight (line 245) | protected int getDialogAvatarHeight() {
method isDialogDividerEnabled (line 249) | protected boolean isDialogDividerEnabled() {
method getDialogDividerColor (line 253) | protected int getDialogDividerColor() {
method getDialogDividerLeftPadding (line 257) | protected int getDialogDividerLeftPadding() {
method getDialogDividerRightPadding (line 261) | protected int getDialogDividerRightPadding() {
method getDialogItemBackground (line 265) | protected int getDialogItemBackground() {
method getDialogUnreadItemBackground (line 269) | protected int getDialogUnreadItemBackground() {
method isDialogMessageAvatarEnabled (line 273) | protected boolean isDialogMessageAvatarEnabled() {
method getDialogMessageAvatarWidth (line 277) | protected int getDialogMessageAvatarWidth() {
method getDialogMessageAvatarHeight (line 281) | protected int getDialogMessageAvatarHeight() {
FILE: chatkit/src/main/java/com/stfalcon/chatkit/dialogs/DialogsList.java
class DialogsList (line 33) | public class DialogsList extends RecyclerView {
method DialogsList (line 37) | public DialogsList(Context context) {
method DialogsList (line 41) | public DialogsList(Context context, @Nullable AttributeSet attrs) {
method DialogsList (line 46) | public DialogsList(Context context, @Nullable AttributeSet attrs, int ...
method onAttachedToWindow (line 51) | @Override
method setAdapter (line 66) | @Override
method setAdapter (line 77) | public <DIALOG extends IDialog<?>>
method setAdapter (line 89) | public <DIALOG extends IDialog<?>>
method parseStyle (line 105) | @SuppressWarnings("ResourceType")
FILE: chatkit/src/main/java/com/stfalcon/chatkit/dialogs/DialogsListAdapter.java
class DialogsListAdapter (line 52) | @SuppressWarnings("WeakerAccess")
method DialogsListAdapter (line 72) | public DialogsListAdapter(ImageLoader imageLoader) {
method DialogsListAdapter (line 82) | public DialogsListAdapter(@LayoutRes int itemLayoutId, ImageLoader ima...
method DialogsListAdapter (line 93) | public DialogsListAdapter(@LayoutRes int itemLayoutId, Class<? extends...
method onBindViewHolder (line 100) | @SuppressWarnings("unchecked")
method onCreateViewHolder (line 112) | @Override
method getItemCount (line 133) | @Override
method deleteById (line 143) | public void deleteById(String id) {
method isEmpty (line 157) | public boolean isEmpty() {
method clear (line 164) | public void clear() {
method setItems (line 176) | public void setItems(List<DIALOG> items) {
method addItems (line 186) | public void addItems(List<DIALOG> newItems) {
method addItem (line 202) | public void addItem(DIALOG dialog) {
method addItem (line 213) | public void addItem(int position, DIALOG dialog) {
method moveItem (line 224) | public void moveItem(int fromPosition, int toPosition) {
method updateItem (line 236) | public void updateItem(int position, DIALOG item) {
method updateItemById (line 249) | public void updateItemById(DIALOG item) {
method upsertItem (line 267) | public void upsertItem(DIALOG item) {
method getItemById (line 288) | @Nullable
method updateDialogWithMessage (line 310) | @SuppressWarnings("unchecked")
method sortByLastMessageDate (line 331) | public void sortByLastMessageDate() {
method sort (line 347) | public void sort(Comparator<DIALOG> comparator) {
method getImageLoader (line 355) | public ImageLoader getImageLoader() {
method setImageLoader (line 364) | public void setImageLoader(ImageLoader imageLoader) {
method getOnDialogClickListener (line 371) | public OnDialogClickListener getOnDialogClickListener() {
method setOnDialogClickListener (line 380) | public void setOnDialogClickListener(OnDialogClickListener<DIALOG> onD...
method getOnDialogViewClickListener (line 387) | public OnDialogViewClickListener getOnDialogViewClickListener() {
method setOnDialogViewClickListener (line 396) | public void setOnDialogViewClickListener(OnDialogViewClickListener<DIA...
method getOnLongItemClickListener (line 403) | public OnDialogLongClickListener getOnLongItemClickListener() {
method setOnDialogLongClickListener (line 412) | public void setOnDialogLongClickListener(OnDialogLongClickListener<DIA...
method getOnDialogViewLongClickListener (line 419) | public OnDialogViewLongClickListener<DIALOG> getOnDialogViewLongClickL...
method setOnDialogViewLongClickListener (line 428) | public void setOnDialogViewLongClickListener(OnDialogViewLongClickList...
method setDatesFormatter (line 435) | public void setDatesFormatter(DateFormatter.Formatter datesFormatter) {
method setStyle (line 440) | void setStyle(DialogListStyle dialogStyle) {
method getDialogPosition (line 447) | public int getDialogPosition(DIALOG dialog) {
type OnDialogClickListener (line 454) | public interface OnDialogClickListener<DIALOG extends IDialog> {
method onDialogClick (line 455) | void onDialogClick(DIALOG dialog);
type OnDialogViewClickListener (line 458) | public interface OnDialogViewClickListener<DIALOG extends IDialog> {
method onDialogViewClick (line 459) | void onDialogViewClick(View view, DIALOG dialog);
type OnDialogLongClickListener (line 462) | public interface OnDialogLongClickListener<DIALOG extends IDialog> {
method onDialogLongClick (line 463) | void onDialogLongClick(DIALOG dialog);
type OnDialogViewLongClickListener (line 466) | public interface OnDialogViewLongClickListener<DIALOG extends IDialog> {
method onDialogViewLongClick (line 467) | void onDialogViewLongClick(View view, DIALOG dialog);
class BaseDialogViewHolder (line 473) | public abstract static class BaseDialogViewHolder<DIALOG extends IDialog>
method BaseDialogViewHolder (line 483) | public BaseDialogViewHolder(View itemView) {
method setImageLoader (line 487) | void setImageLoader(ImageLoader imageLoader) {
method setOnDialogClickListener (line 491) | protected void setOnDialogClickListener(OnDialogClickListener<DIALOG...
method setOnDialogViewClickListener (line 495) | protected void setOnDialogViewClickListener(OnDialogViewClickListene...
method setOnLongItemClickListener (line 499) | protected void setOnLongItemClickListener(OnDialogLongClickListener<...
method setOnDialogViewLongClickListener (line 503) | protected void setOnDialogViewLongClickListener(OnDialogViewLongClic...
method setDatesFormatter (line 507) | public void setDatesFormatter(DateFormatter.Formatter dateHeadersFor...
class DialogViewHolder (line 512) | public static class DialogViewHolder<DIALOG extends IDialog> extends B...
method DialogViewHolder (line 525) | public DialogViewHolder(View itemView) {
method applyStyle (line 540) | private void applyStyle() {
method applyDefaultStyle (line 586) | private void applyDefaultStyle() {
method applyUnreadStyle (line 609) | private void applyUnreadStyle() {
method onBind (line 633) | @Override
method getDateString (line 703) | protected String getDateString(Date date) {
method getDialogStyle (line 707) | protected DialogListStyle getDialogStyle() {
method setDialogStyle (line 711) | protected void setDialogStyle(DialogListStyle dialogStyle) {
FILE: chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageHolders.java
class MessageHolders (line 36) | @SuppressWarnings("WeakerAccess")
method MessageHolders (line 56) | public MessageHolders() {
method setIncomingTextConfig (line 75) | public MessageHolders setIncomingTextConfig(
method setIncomingTextConfig (line 91) | public MessageHolders setIncomingTextConfig(
method setIncomingTextHolder (line 107) | public MessageHolders setIncomingTextHolder(
method setIncomingTextHolder (line 120) | public MessageHolders setIncomingTextHolder(
method setIncomingTextLayout (line 134) | public MessageHolders setIncomingTextLayout(@LayoutRes int layout) {
method setIncomingTextLayout (line 146) | public MessageHolders setIncomingTextLayout(@LayoutRes int layout, Obj...
method setOutcomingTextConfig (line 159) | public MessageHolders setOutcomingTextConfig(
method setOutcomingTextConfig (line 175) | public MessageHolders setOutcomingTextConfig(
method setOutcomingTextHolder (line 191) | public MessageHolders setOutcomingTextHolder(
method setOutcomingTextHolder (line 204) | public MessageHolders setOutcomingTextHolder(
method setOutcomingTextLayout (line 218) | public MessageHolders setOutcomingTextLayout(@LayoutRes int layout) {
method setOutcomingTextLayout (line 230) | public MessageHolders setOutcomingTextLayout(@LayoutRes int layout, Ob...
method setIncomingImageConfig (line 243) | public MessageHolders setIncomingImageConfig(
method setIncomingImageConfig (line 259) | public MessageHolders setIncomingImageConfig(
method setIncomingImageHolder (line 275) | public MessageHolders setIncomingImageHolder(
method setIncomingImageHolder (line 288) | public MessageHolders setIncomingImageHolder(
method setIncomingImageLayout (line 302) | public MessageHolders setIncomingImageLayout(@LayoutRes int layout) {
method setIncomingImageLayout (line 314) | public MessageHolders setIncomingImageLayout(@LayoutRes int layout, Ob...
method setOutcomingImageConfig (line 327) | public MessageHolders setOutcomingImageConfig(
method setOutcomingImageConfig (line 343) | public MessageHolders setOutcomingImageConfig(
method setOutcomingImageHolder (line 359) | public MessageHolders setOutcomingImageHolder(
method setOutcomingImageHolder (line 372) | public MessageHolders setOutcomingImageHolder(
method setOutcomingImageLayout (line 386) | public MessageHolders setOutcomingImageLayout(@LayoutRes int layout) {
method setOutcomingImageLayout (line 398) | public MessageHolders setOutcomingImageLayout(@LayoutRes int layout, O...
method setDateHeaderConfig (line 411) | public MessageHolders setDateHeaderConfig(
method setDateHeaderHolder (line 425) | public MessageHolders setDateHeaderHolder(@NonNull Class<? extends Vie...
method setDateHeaderLayout (line 436) | public MessageHolders setDateHeaderLayout(@LayoutRes int layout) {
method registerContentType (line 451) | public <TYPE extends MessageContentType>
method registerContentType (line 475) | public <TYPE extends MessageContentType>
method registerContentType (line 506) | public <TYPE extends MessageContentType>
type ContentChecker (line 531) | public interface ContentChecker<MESSAGE extends IMessage> {
method hasContentFor (line 540) | boolean hasContentFor(MESSAGE message, byte type);
method getHolder (line 547) | protected ViewHolder getHolder(ViewGroup parent, int viewType, Message...
method bind (line 574) | @SuppressWarnings("unchecked")
method getViewType (line 605) | protected int getViewType(Object item, String senderId) {
method getHolder (line 621) | private ViewHolder getHolder(ViewGroup parent, HolderConfig holderConfig,
method getHolder (line 626) | private <HOLDER extends ViewHolder>
method getContentViewType (line 652) | @SuppressWarnings("unchecked")
class BaseMessageViewHolder (line 683) | public static abstract class BaseMessageViewHolder<MESSAGE extends IMe...
method BaseMessageViewHolder (line 697) | @Deprecated
method BaseMessageViewHolder (line 702) | public BaseMessageViewHolder(View itemView, Object payload) {
method isSelected (line 712) | public boolean isSelected() {
method isSelectionModeEnabled (line 721) | public boolean isSelectionModeEnabled() {
method getImageLoader (line 730) | public ImageLoader getImageLoader() {
method configureLinksBehavior (line 734) | protected void configureLinksBehavior(final TextView text) {
class IncomingTextMessageViewHolder (line 753) | public static class IncomingTextMessageViewHolder<MESSAGE extends IMes...
method IncomingTextMessageViewHolder (line 761) | @Deprecated
method IncomingTextMessageViewHolder (line 767) | public IncomingTextMessageViewHolder(View itemView, Object payload) {
method onBind (line 772) | @Override
method applyStyle (line 784) | @SuppressLint("WrongConstant")
method init (line 828) | private void init(View itemView) {
class OutcomingTextMessageViewHolder (line 838) | public static class OutcomingTextMessageViewHolder<MESSAGE extends IMe...
method OutcomingTextMessageViewHolder (line 846) | @Deprecated
method OutcomingTextMessageViewHolder (line 852) | public OutcomingTextMessageViewHolder(View itemView, Object payload) {
method onBind (line 857) | @Override
method applyStyle (line 869) | @SuppressLint("WrongConstant")
method init (line 900) | private void init(View itemView) {
class IncomingImageMessageViewHolder (line 910) | public static class IncomingImageMessageViewHolder<MESSAGE extends Mes...
method IncomingImageMessageViewHolder (line 916) | @Deprecated
method IncomingImageMessageViewHolder (line 922) | public IncomingImageMessageViewHolder(View itemView, Object payload) {
method onBind (line 927) | @Override
method applyStyle (line 939) | @SuppressLint("WrongConstant")
method getPayloadForImageLoader (line 959) | protected Object getPayloadForImageLoader(MESSAGE message) {
method init (line 963) | private void init(View itemView) {
class OutcomingImageMessageViewHolder (line 981) | public static class OutcomingImageMessageViewHolder<MESSAGE extends Me...
method OutcomingImageMessageViewHolder (line 987) | @Deprecated
method OutcomingImageMessageViewHolder (line 993) | public OutcomingImageMessageViewHolder(View itemView, Object payload) {
method onBind (line 998) | @Override
method applyStyle (line 1010) | @SuppressLint("WrongConstant")
method getPayloadForImageLoader (line 1030) | protected Object getPayloadForImageLoader(MESSAGE message) {
method init (line 1034) | private void init(View itemView) {
class DefaultDateHeaderViewHolder (line 1052) | public static class DefaultDateHeaderViewHolder extends ViewHolder<Date>
method DefaultDateHeaderViewHolder (line 1059) | public DefaultDateHeaderViewHolder(View itemView) {
method onBind (line 1064) | @Override
method applyStyle (line 1073) | @SuppressLint("WrongConstant")
class DefaultStringHeaderViewHolder (line 1088) | public static class DefaultStringHeaderViewHolder extends ViewHolder<S...
method DefaultStringHeaderViewHolder (line 1093) | public DefaultStringHeaderViewHolder(View itemView) {
method onBind (line 1098) | @Override
method applyStyle (line 1105) | @SuppressLint("WrongConstant")
class BaseIncomingMessageViewHolder (line 1121) | public abstract static class BaseIncomingMessageViewHolder<MESSAGE ext...
method BaseIncomingMessageViewHolder (line 1127) | @Deprecated
method BaseIncomingMessageViewHolder (line 1133) | public BaseIncomingMessageViewHolder(View itemView, Object payload) {
method onBind (line 1138) | @Override
method applyStyle (line 1156) | @SuppressLint("WrongConstant")
method init (line 1173) | private void init(View itemView) {
class BaseOutcomingMessageViewHolder (line 1182) | public abstract static class BaseOutcomingMessageViewHolder<MESSAGE ex...
method BaseOutcomingMessageViewHolder (line 1187) | @Deprecated
method BaseOutcomingMessageViewHolder (line 1193) | public BaseOutcomingMessageViewHolder(View itemView, Object payload) {
method onBind (line 1198) | @Override
method applyStyle (line 1205) | @SuppressLint("WrongConstant")
method init (line 1216) | private void init(View itemView) {
type DefaultMessageViewHolder (line 1225) | interface DefaultMessageViewHolder {
method applyStyle (line 1226) | void applyStyle(MessagesListStyle style);
class DefaultIncomingTextMessageViewHolder (line 1229) | private static class DefaultIncomingTextMessageViewHolder
method DefaultIncomingTextMessageViewHolder (line 1232) | public DefaultIncomingTextMessageViewHolder(View itemView) {
class DefaultOutcomingTextMessageViewHolder (line 1237) | private static class DefaultOutcomingTextMessageViewHolder
method DefaultOutcomingTextMessageViewHolder (line 1240) | public DefaultOutcomingTextMessageViewHolder(View itemView) {
class DefaultIncomingImageMessageViewHolder (line 1245) | private static class DefaultIncomingImageMessageViewHolder
method DefaultIncomingImageMessageViewHolder (line 1248) | public DefaultIncomingImageMessageViewHolder(View itemView) {
class DefaultOutcomingImageMessageViewHolder (line 1253) | private static class DefaultOutcomingImageMessageViewHolder
method DefaultOutcomingImageMessageViewHolder (line 1256) | public DefaultOutcomingImageMessageViewHolder(View itemView) {
class ContentTypeConfig (line 1261) | private static class ContentTypeConfig<TYPE extends MessageContentType> {
method ContentTypeConfig (line 1267) | private ContentTypeConfig(
class HolderConfig (line 1276) | private static class HolderConfig<T extends IMessage> {
method HolderConfig (line 1282) | HolderConfig(Class<? extends BaseMessageViewHolder<? extends T>> hol...
method HolderConfig (line 1287) | HolderConfig(Class<? extends BaseMessageViewHolder<? extends T>> hol...
FILE: chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageInput.java
class MessageInput (line 42) | @SuppressWarnings({"WeakerAccess", "unused"})
method run (line 58) | @Override
method MessageInput (line 68) | public MessageInput(Context context) {
method MessageInput (line 73) | public MessageInput(Context context, AttributeSet attrs) {
method MessageInput (line 78) | public MessageInput(Context context, AttributeSet attrs, int defStyleA...
method setInputListener (line 88) | public void setInputListener(InputListener inputListener) {
method setAttachmentsListener (line 97) | public void setAttachmentsListener(AttachmentsListener attachmentsList...
method getInputEditText (line 106) | public EditText getInputEditText() {
method getButton (line 115) | public ImageButton getButton() {
method onClick (line 119) | @Override
method onTextChanged (line 138) | @Override
method beforeTextChanged (line 156) | @Override
method afterTextChanged (line 164) | @Override
method onFocusChange (line 169) | @Override
method onSubmit (line 177) | private boolean onSubmit() {
method onAddAttachments (line 181) | private void onAddAttachments() {
method init (line 185) | private void init(Context context, AttributeSet attrs) {
method init (line 227) | private void init(Context context) {
method setCursor (line 243) | private void setCursor(Drawable drawable) {
method setTypingListener (line 268) | public void setTypingListener(TypingListener typingListener) {
type InputListener (line 275) | public interface InputListener {
method onSubmit (line 283) | boolean onSubmit(CharSequence input);
type AttachmentsListener (line 289) | public interface AttachmentsListener {
method onAddAttachments (line 294) | void onAddAttachments();
type TypingListener (line 300) | public interface TypingListener {
method onStartTyping (line 305) | void onStartTyping();
method onStopTyping (line 310) | void onStopTyping();
FILE: chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageInputStyle.java
class MessageInputStyle (line 35) | @SuppressWarnings("WeakerAccess")
method parse (line 89) | static MessageInputStyle parse(Context context, AttributeSet attrs) {
method MessageInputStyle (line 158) | private MessageInputStyle(Context context, AttributeSet attrs) {
method getSelector (line 162) | private Drawable getSelector(@ColorInt int normalColor, @ColorInt int ...
method showAttachmentButton (line 179) | protected boolean showAttachmentButton() {
method getAttachmentButtonBackground (line 183) | protected Drawable getAttachmentButtonBackground() {
method getAttachmentButtonIcon (line 192) | protected Drawable getAttachmentButtonIcon() {
method getAttachmentButtonWidth (line 201) | protected int getAttachmentButtonWidth() {
method getAttachmentButtonHeight (line 205) | protected int getAttachmentButtonHeight() {
method getAttachmentButtonMargin (line 209) | protected int getAttachmentButtonMargin() {
method getInputButtonBackground (line 213) | protected Drawable getInputButtonBackground() {
method getInputButtonIcon (line 222) | protected Drawable getInputButtonIcon() {
method getInputButtonMargin (line 231) | protected int getInputButtonMargin() {
method getInputButtonWidth (line 235) | protected int getInputButtonWidth() {
method getInputButtonHeight (line 239) | protected int getInputButtonHeight() {
method getInputMaxLines (line 243) | protected int getInputMaxLines() {
method getInputHint (line 247) | protected String getInputHint() {
method getInputText (line 251) | protected String getInputText() {
method getInputTextSize (line 255) | protected int getInputTextSize() {
method getInputTextColor (line 259) | protected int getInputTextColor() {
method getInputHintColor (line 263) | protected int getInputHintColor() {
method getInputBackground (line 267) | protected Drawable getInputBackground() {
method getInputCursorDrawable (line 271) | protected Drawable getInputCursorDrawable() {
method getInputDefaultPaddingLeft (line 275) | protected int getInputDefaultPaddingLeft() {
method getInputDefaultPaddingRight (line 279) | protected int getInputDefaultPaddingRight() {
method getInputDefaultPaddingTop (line 283) | protected int getInputDefaultPaddingTop() {
method getInputDefaultPaddingBottom (line 287) | protected int getInputDefaultPaddingBottom() {
method getDelayTypingStatus (line 291) | int getDelayTypingStatus() {
FILE: chatkit/src/main/java/com/stfalcon/chatkit/messages/MessagesList.java
class MessagesList (line 33) | public class MessagesList extends RecyclerView {
method MessagesList (line 36) | public MessagesList(Context context) {
method MessagesList (line 40) | public MessagesList(Context context, @Nullable AttributeSet attrs) {
method MessagesList (line 45) | public MessagesList(Context context, @Nullable AttributeSet attrs, int...
method setAdapter (line 54) | @Override
method setAdapter (line 65) | public <MESSAGE extends IMessage>
method setAdapter (line 77) | public <MESSAGE extends IMessage>
method parseStyle (line 98) | @SuppressWarnings("ResourceType")
FILE: chatkit/src/main/java/com/stfalcon/chatkit/messages/MessagesListAdapter.java
class MessagesListAdapter (line 55) | @SuppressWarnings("WeakerAccess")
method MessagesListAdapter (line 90) | public MessagesListAdapter(String senderId, ImageLoader imageLoader) {
method MessagesListAdapter (line 101) | public MessagesListAdapter(String senderId, MessageHolders holders,
method onCreateViewHolder (line 109) | @Override
method onBindViewHolder (line 114) | @SuppressWarnings("unchecked")
method getItemCount (line 132) | @Override
method getItemViewType (line 137) | @Override
method onLoadMore (line 142) | @Override
method getMessagesCount (line 149) | @Override
method addToStart (line 170) | public void addToStart(MESSAGE message, boolean scroll) {
method addToEnd (line 197) | public void addToEnd(List<MESSAGE> messages, boolean reverse) {
method update (line 225) | public boolean update(MESSAGE message) {
method update (line 235) | public boolean update(String oldId, MESSAGE newMessage) {
method updateAndMoveToStart (line 252) | public void updateAndMoveToStart(MESSAGE newMessage) {
method upsert (line 268) | public void upsert(MESSAGE message) {
method upsert (line 280) | public void upsert(MESSAGE message, boolean moveToStartIfUpdate) {
method delete (line 297) | public void delete(MESSAGE message) {
method delete (line 306) | public void delete(List<MESSAGE> messages) {
method deleteById (line 326) | public void deleteById(String id) {
method deleteByIds (line 340) | public void deleteByIds(String[] ids) {
method setMaxItemsCount (line 355) | public void setMaxItemsCount(int maxItemsCount) {
method setFocusedMessage (line 359) | public void setFocusedMessage(MESSAGE message) {
method isEmpty (line 368) | public boolean isEmpty() {
method clear (line 375) | public void clear() {
method clear (line 382) | public void clear(boolean notifyDataSetChanged) {
method scrollToPosition (line 391) | public void scrollToPosition(int position) {
method scrollToTop (line 397) | public void scrollToTop() {
method scrollToBottom (line 403) | public void scrollToBottom() {
method enableSelectionMode (line 414) | public void enableSelectionMode(SelectionListener selectionListener) {
method disableSelectionMode (line 425) | public void disableSelectionMode() {
method enableDateHeader (line 430) | public void enableDateHeader(boolean enable) {
method enableStackFromEnd (line 434) | public void enableStackFromEnd(boolean enable) {
method setLoadingMessage (line 440) | public void setLoadingMessage(String message) {
method removeLoadingMessageIfNeeded (line 451) | private void removeLoadingMessageIfNeeded() {
method getSelectedMessages (line 463) | @SuppressWarnings("unchecked")
method getMessages (line 474) | public ArrayList<MESSAGE> getMessages() {
method getSelectedMessagesText (line 491) | public String getSelectedMessagesText(Formatter<MESSAGE> formatter, bo...
method copySelectedMessagesText (line 505) | public String copySelectedMessagesText(Context context, Formatter<MESS...
method unselectAllItems (line 515) | public void unselectAllItems() {
method deleteSelectedMessages (line 532) | public void deleteSelectedMessages() {
method setOnMessageClickListener (line 543) | public void setOnMessageClickListener(OnMessageClickListener<MESSAGE> ...
method setOnMessageViewClickListener (line 552) | public void setOnMessageViewClickListener(OnMessageViewClickListener<M...
method registerViewClickListener (line 562) | public void registerViewClickListener(int viewId, OnMessageViewClickLi...
method setOnMessageLongClickListener (line 571) | public void setOnMessageLongClickListener(OnMessageLongClickListener<M...
method setOnMessageViewLongClickListener (line 580) | public void setOnMessageViewLongClickListener(OnMessageViewLongClickLi...
method setOnMessageViewFocusListener (line 584) | public void setOnMessageViewFocusListener(OnMessageViewFocusListener<M...
method setLoadMoreListener (line 593) | public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
method setDateHeadersFormatter (line 600) | public void setDateHeadersFormatter(DateFormatter.Formatter dateHeader...
method recountDateHeaders (line 607) | private void recountDateHeaders() {
method generateDateHeaders (line 630) | protected void generateDateHeaders(List<MESSAGE> messages) {
method getMessagePosition (line 650) | public int getMessagePosition(MESSAGE message) {
method getMessagePositionById (line 658) | @SuppressWarnings("unchecked")
method isPreviousSameDate (line 672) | @SuppressWarnings("unchecked")
method isPreviousSameAuthor (line 681) | @SuppressWarnings("unchecked")
method incrementSelectedItemsCount (line 689) | private void incrementSelectedItemsCount() {
method decrementSelectedItemsCount (line 694) | private void decrementSelectedItemsCount() {
method notifySelectionChanged (line 701) | private void notifySelectionChanged() {
method notifyMessageClicked (line 707) | private void notifyMessageClicked(MESSAGE message) {
method notifyMessageViewClicked (line 713) | private void notifyMessageViewClicked(View view, MESSAGE message) {
method notifyMessageLongClicked (line 719) | private void notifyMessageLongClicked(MESSAGE message) {
method notifyMessageViewLongClicked (line 725) | private void notifyMessageViewLongClicked(View view, MESSAGE message) {
method notifyMessageViewFocused (line 731) | private void notifyMessageViewFocused(View view, MESSAGE message) {
method getMessageClickListener (line 737) | private View.OnClickListener getMessageClickListener(final Wrapper<MES...
method getMessageLongClickListener (line 757) | private View.OnLongClickListener getMessageLongClickListener(final Wra...
method getMessageFocusChangeListener (line 770) | private View.OnFocusChangeListener getMessageFocusChangeListener(final...
method getSelectedText (line 803) | private String getSelectedText(Formatter<MESSAGE> formatter, boolean r...
method copyToClipboard (line 820) | private void copyToClipboard(Context context, String copiedText) {
method trimEnd (line 826) | private void trimEnd() {
method setLayoutManager (line 842) | void setLayoutManager(RecyclerView.LayoutManager layoutManager) {
method setStyle (line 846) | void setStyle(MessagesListStyle style) {
class Wrapper (line 853) | public static class Wrapper<DATA> {
method Wrapper (line 857) | Wrapper(DATA item) {
type OnLoadMoreListener (line 869) | public interface OnLoadMoreListener {
method onLoadMore (line 877) | void onLoadMore(int page, int totalItemsCount);
type SelectionListener (line 883) | public interface SelectionListener {
method onSelectionChanged (line 890) | void onSelectionChanged(int count);
type OnMessageClickListener (line 896) | public interface OnMessageClickListener<MESSAGE extends IMessage> {
method onMessageClick (line 903) | void onMessageClick(MESSAGE message);
type OnMessageViewClickListener (line 909) | public interface OnMessageViewClickListener<MESSAGE extends IMessage> {
method onMessageViewClick (line 916) | void onMessageViewClick(View view, MESSAGE message);
type OnMessageViewFocusListener (line 919) | public interface OnMessageViewFocusListener<MESSAGE extends IMessage> {
method onMessageViewFocus (line 920) | void onMessageViewFocus(View view, MESSAGE message);
type OnMessageLongClickListener (line 926) | public interface OnMessageLongClickListener<MESSAGE extends IMessage> {
method onMessageLongClick (line 933) | void onMessageLongClick(MESSAGE message);
type OnMessageViewLongClickListener (line 939) | public interface OnMessageViewLongClickListener<MESSAGE extends IMessa...
method onMessageViewLongClick (line 946) | void onMessageViewLongClick(View view, MESSAGE message);
type Formatter (line 952) | public interface Formatter<MESSAGE> {
method format (line 960) | String format(MESSAGE message);
class HoldersConfig (line 966) | @Deprecated
method setIncoming (line 975) | @Deprecated
method setIncomingHolder (line 985) | @Deprecated
method setIncomingLayout (line 995) | @Deprecated
method setOutcoming (line 1006) | @Deprecated
method setOutcomingHolder (line 1016) | @Deprecated
method setOutcomingLayout (line 1026) | @Deprecated
method setDateHeader (line 1037) | @Deprecated
class BaseMessageViewHolder (line 1046) | @Deprecated
method BaseMessageViewHolder (line 1057) | public BaseMessageViewHolder(View itemView) {
method isSelected (line 1066) | public boolean isSelected() {
method isSelectionModeEnabled (line 1075) | public boolean isSelectionModeEnabled() {
method getImageLoader (line 1084) | public ImageLoader getImageLoader() {
method configureLinksBehavior (line 1088) | protected void configureLinksBehavior(final TextView text) {
class DefaultDateHeaderViewHolder (line 1108) | @Deprecated
method DefaultDateHeaderViewHolder (line 1116) | public DefaultDateHeaderViewHolder(View itemView) {
method onBind (line 1121) | @Override
method applyStyle (line 1130) | @SuppressLint("WrongConstant")
class IncomingMessageViewHolder (line 1148) | @Deprecated
method IncomingMessageViewHolder (line 1153) | public IncomingMessageViewHolder(View itemView) {
class OutcomingMessageViewHolder (line 1161) | @Deprecated
method OutcomingMessageViewHolder (line 1165) | public OutcomingMessageViewHolder(View itemView) {
FILE: chatkit/src/main/java/com/stfalcon/chatkit/messages/MessagesListStyle.java
class MessagesListStyle (line 37) | @SuppressWarnings("WeakerAccess")
method parse (line 109) | static MessagesListStyle parse(Context context, AttributeSet attrs) {
method MessagesListStyle (line 223) | private MessagesListStyle(Context context, AttributeSet attrs) {
method getMessageSelector (line 227) | private Drawable getMessageSelector(@ColorInt int normalColor, @ColorI...
method getTextAutoLinkMask (line 244) | protected int getTextAutoLinkMask() {
method getIncomingTextLinkColor (line 248) | protected int getIncomingTextLinkColor() {
method getOutcomingTextLinkColor (line 252) | protected int getOutcomingTextLinkColor() {
method getIncomingAvatarWidth (line 256) | protected int getIncomingAvatarWidth() {
method getIncomingAvatarHeight (line 260) | protected int getIncomingAvatarHeight() {
method getIncomingDefaultBubblePaddingLeft (line 264) | protected int getIncomingDefaultBubblePaddingLeft() {
method getIncomingDefaultBubblePaddingRight (line 268) | protected int getIncomingDefaultBubblePaddingRight() {
method getIncomingDefaultBubblePaddingTop (line 272) | protected int getIncomingDefaultBubblePaddingTop() {
method getIncomingDefaultBubblePaddingBottom (line 276) | protected int getIncomingDefaultBubblePaddingBottom() {
method getIncomingTextColor (line 280) | protected int getIncomingTextColor() {
method getIncomingTextSize (line 284) | protected int getIncomingTextSize() {
method getIncomingTextStyle (line 288) | protected int getIncomingTextStyle() {
method getOutcomingBubbleDrawable (line 292) | protected Drawable getOutcomingBubbleDrawable() {
method getOutcomingImageOverlayDrawable (line 301) | protected Drawable getOutcomingImageOverlayDrawable() {
method getOutcomingDefaultBubblePaddingLeft (line 310) | protected int getOutcomingDefaultBubblePaddingLeft() {
method getOutcomingDefaultBubblePaddingRight (line 314) | protected int getOutcomingDefaultBubblePaddingRight() {
method getOutcomingDefaultBubblePaddingTop (line 318) | protected int getOutcomingDefaultBubblePaddingTop() {
method getOutcomingDefaultBubblePaddingBottom (line 322) | protected int getOutcomingDefaultBubblePaddingBottom() {
method getOutcomingTextColor (line 326) | protected int getOutcomingTextColor() {
method getOutcomingTextSize (line 330) | protected int getOutcomingTextSize() {
method getOutcomingTextStyle (line 334) | protected int getOutcomingTextStyle() {
method showOutcomingTime (line 338) | protected boolean showOutcomingTime() {
method getOutcomingTimeTextColor (line 342) | protected int getOutcomingTimeTextColor() {
method getOutcomingTimeTextSize (line 346) | protected int getOutcomingTimeTextSize() {
method getOutcomingTimeTextStyle (line 350) | protected int getOutcomingTimeTextStyle() {
method getOutcomingImageTimeTextColor (line 354) | protected int getOutcomingImageTimeTextColor() {
method getOutcomingImageTimeTextSize (line 358) | protected int getOutcomingImageTimeTextSize() {
method getOutcomingImageTimeTextStyle (line 362) | protected int getOutcomingImageTimeTextStyle() {
method getDateHeaderTextColor (line 366) | protected int getDateHeaderTextColor() {
method getDateHeaderTextSize (line 370) | protected int getDateHeaderTextSize() {
method getDateHeaderTextStyle (line 374) | protected int getDateHeaderTextStyle() {
method getDateHeaderPadding (line 378) | protected int getDateHeaderPadding() {
method getDateHeaderFormat (line 382) | protected String getDateHeaderFormat() {
method showIncomingTime (line 386) | protected boolean showIncomingTime() {
method getIncomingTimeTextSize (line 390) | protected int getIncomingTimeTextSize() {
method getIncomingTimeTextStyle (line 394) | protected int getIncomingTimeTextStyle() {
method getIncomingTimeTextColor (line 398) | protected int getIncomingTimeTextColor() {
method getIncomingImageTimeTextColor (line 402) | protected int getIncomingImageTimeTextColor() {
method getIncomingImageTimeTextSize (line 406) | protected int getIncomingImageTimeTextSize() {
method getIncomingImageTimeTextStyle (line 410) | protected int getIncomingImageTimeTextStyle() {
method getIncomingBubbleDrawable (line 414) | protected Drawable getIncomingBubbleDrawable() {
method getIncomingBubbleSelectedDrawable (line 423) | protected Drawable getIncomingBubbleSelectedDrawable() {
method getIncomingImageOverlayDrawable (line 428) | protected Drawable getIncomingImageOverlayDrawable() {
method isMessageFocusable (line 437) | protected boolean isMessageFocusable() {
FILE: chatkit/src/main/java/com/stfalcon/chatkit/messages/RecyclerScrollMoreListener.java
class RecyclerScrollMoreListener (line 24) | class RecyclerScrollMoreListener
method RecyclerScrollMoreListener (line 36) | RecyclerScrollMoreListener(LinearLayoutManager layoutManager, OnLoadMo...
method getLastVisibleItem (line 41) | private int getLastVisibleItem(int[] lastVisibleItemPositions) {
method onScrolled (line 55) | @Override
type OnLoadMoreListener (line 127) | interface OnLoadMoreListener {
method onLoadMore (line 128) | void onLoadMore(int page, int total);
method getMessagesCount (line 130) | int getMessagesCount();
FILE: chatkit/src/main/java/com/stfalcon/chatkit/utils/DateFormatter.java
class DateFormatter (line 24) | public final class DateFormatter {
method DateFormatter (line 25) | private DateFormatter() {
method format (line 29) | public static String format(Date date, Template template) {
method format (line 33) | public static String format(Date date, String format) {
method isSameDay (line 39) | public static boolean isSameDay(Date date1, Date date2) {
method isSameDay (line 50) | public static boolean isSameDay(Calendar cal1, Calendar cal2) {
method isSameYear (line 59) | public static boolean isSameYear(Date date1, Date date2) {
method isSameYear (line 70) | public static boolean isSameYear(Calendar cal1, Calendar cal2) {
method isToday (line 78) | public static boolean isToday(Calendar calendar) {
method isToday (line 82) | public static boolean isToday(Date date) {
method isYesterday (line 86) | public static boolean isYesterday(Calendar calendar) {
method isYesterday (line 92) | public static boolean isYesterday(Date date) {
method isCurrentYear (line 98) | public static boolean isCurrentYear(Date date) {
method isCurrentYear (line 102) | public static boolean isCurrentYear(Calendar calendar) {
type Formatter (line 109) | public interface Formatter {
method format (line 117) | String format(Date date);
type Template (line 120) | public enum Template {
method Template (line 127) | Template(String template) {
method get (line 131) | public String get() {
FILE: chatkit/src/main/java/com/stfalcon/chatkit/utils/RoundedImageView.java
class RoundedImageView (line 32) | public class RoundedImageView extends AppCompatImageView {
method RoundedImageView (line 39) | public RoundedImageView(Context context) {
method RoundedImageView (line 43) | public RoundedImageView(Context context, AttributeSet attrs) {
method RoundedImageView (line 47) | public RoundedImageView(Context context, AttributeSet attrs, int defSt...
method drawableStateChanged (line 51) | @Override
method setImageDrawable (line 57) | @Override
method setImageBitmap (line 65) | @Override
method setImageResource (line 73) | @Override
method setImageURI (line 83) | @Override
method setCorners (line 89) | public void setCorners(@DimenRes int leftTop, @DimenRes int rightTop,
method setCorners (line 99) | public void setCorners(float leftTop, float rightTop, float rightBotto...
method resolveResource (line 109) | private Drawable resolveResource() {
method updateDrawable (line 122) | private void updateDrawable() {
class RoundedCornerDrawable (line 128) | private static class RoundedCornerDrawable extends Drawable {
method RoundedCornerDrawable (line 143) | private RoundedCornerDrawable(Bitmap bitmap, Resources r) {
method fromBitmap (line 157) | private static RoundedCornerDrawable fromBitmap(Bitmap bitmap, Resou...
method fromDrawable (line 162) | private static Drawable fromDrawable(Drawable drawable, Resources r) {
method drawableToBitmap (line 182) | private static Bitmap drawableToBitmap(Drawable drawable) {
method configureBounds (line 204) | private void configureBounds(Canvas canvas) {
method applyScaleToRadii (line 211) | private void applyScaleToRadii(Matrix m) {
method draw (line 219) | @Override
method setCornerRadii (line 231) | void setCornerRadii(float[] radii) {
method getOpacity (line 239) | @Override
method setAlpha (line 246) | @Override
method setColorFilter (line 252) | @Override
method setDither (line 258) | @Override
method setFilterBitmap (line 264) | @Override
method getIntrinsicWidth (line 270) | @Override
method getIntrinsicHeight (line 275) | @Override
FILE: chatkit/src/main/java/com/stfalcon/chatkit/utils/ShapeImageView.java
class ShapeImageView (line 29) | public class ShapeImageView extends androidx.appcompat.widget.AppCompatI...
method ShapeImageView (line 32) | public ShapeImageView(Context context) {
method ShapeImageView (line 37) | public ShapeImageView(Context context, AttributeSet attrs) {
method onSizeChanged (line 42) | @Override
method onDraw (line 59) | @Override
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/data/BrowseSection.java
class BrowseSection (line 7) | public class BrowseSection {
method BrowseSection (line 24) | public BrowseSection(int id, String title, int type, int resId) {
method BrowseSection (line 28) | public BrowseSection(int id, String title, int type, String iconUrl) {
method BrowseSection (line 32) | public BrowseSection(int id, String title, int type, String iconUrl, b...
method BrowseSection (line 36) | public BrowseSection(int id, String title, int type, String iconUrl, b...
method BrowseSection (line 40) | public BrowseSection(int id, String title, int type, int resId, boolea...
method BrowseSection (line 44) | public BrowseSection(int id, String title, int type, int resId, boolea...
method BrowseSection (line 48) | public BrowseSection(int id, String title, int type, int resId, String...
method getTitle (line 58) | public String getTitle() {
method setTitle (line 62) | public void setTitle(String title) {
method getId (line 66) | public int getId() {
method getType (line 70) | public int getType() {
method setType (line 74) | public void setType(int type) {
method getResId (line 78) | public int getResId() {
method getIconUrl (line 82) | public String getIconUrl() {
method isAuthOnly (line 86) | public boolean isAuthOnly() {
method setEnabled (line 90) | public void setEnabled(boolean enabled) {
method isEnabled (line 94) | public boolean isEnabled() {
method getData (line 98) | public Object getData() {
method isDefault (line 105) | public boolean isDefault() {
method equals (line 109) | @Override
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/data/Playlist.java
class Playlist (line 12) | public class Playlist {
method Playlist (line 21) | private Playlist() {
method instance (line 28) | public static Playlist instance() {
method clear (line 39) | public void clear() {
method clearPosition (line 44) | public void clearPosition() {
method addAll (line 51) | public void addAll(List<Video> videos) {
method add (line 61) | public void add(Video video) {
method next (line 92) | public void next(Video video) {
method remove (line 114) | public void remove(Video video) {
method contains (line 145) | public boolean contains(Video video) {
method containsAfterCurrent (line 153) | public boolean containsAfterCurrent(Video video) {
method getNext (line 189) | public Video getNext() {
method getPrevious (line 203) | public Video getPrevious() {
method setCurrent (line 211) | public void setCurrent(Video video) {
method getCurrent (line 226) | public Video getCurrent() {
method getAll (line 234) | public List<Video> getAll() {
method getChangedItems (line 238) | public List<Video> getChangedItems() {
method hasNext (line 242) | public boolean hasNext() {
method getAllAfterCurrent (line 246) | public List<Video> getAllAfterCurrent() {
method removeAllAfterCurrent (line 259) | public void removeAllAfterCurrent() {
method trimPlaylist (line 275) | private void trimPlaylist() {
method stripPrevItem (line 289) | private void stripPrevItem() {
method replace (line 306) | private void replace(Video origin, Video newItem) {
method onNewSession (line 314) | public void onNewSession() {
method sync (line 321) | public void sync(Video origin) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/data/SettingsGroup.java
class SettingsGroup (line 5) | public class SettingsGroup {
method from (line 9) | public static SettingsGroup from(List<SettingsItem> items, BrowseSecti...
method getItems (line 17) | public List<SettingsItem> getItems() {
method getCategory (line 21) | public BrowseSection getCategory() {
method isEmpty (line 25) | public boolean isEmpty() {
method getTitle (line 29) | public String getTitle() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/data/SettingsItem.java
class SettingsItem (line 3) | public class SettingsItem {
method SettingsItem (line 8) | public SettingsItem(String title, Runnable onClick) {
method SettingsItem (line 12) | public SettingsItem(String title, Runnable onClick, int imageResId) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/data/SimpleMediaItem.java
class SimpleMediaItem (line 6) | public final class SimpleMediaItem implements MediaItem {
method SimpleMediaItem (line 31) | private SimpleMediaItem() {
method from (line 34) | public static MediaItem from(MediaItemMetadata metadata) {
method from (line 49) | public static MediaItem from(Video video) {
method getType (line 79) | @Override
method isLive (line 84) | @Override
method isUpcoming (line 89) | @Override
method isShorts (line 94) | @Override
method isMovie (line 99) | @Override
method getPercentWatched (line 104) | @Override
method getStartTimeSeconds (line 109) | @Override
method getAuthor (line 114) | @Override
method getFeedbackToken (line 119) | @Override
method getFeedbackToken2 (line 124) | @Override
method getPlaylistId (line 129) | @Override
method getPlaylistIndex (line 134) | @Override
method getParams (line 139) | @Override
method getReloadPageKey (line 144) | @Override
method hasNewContent (line 149) | @Override
method getId (line 154) | @Override
method getTitle (line 159) | @Override
method getSecondTitle (line 164) | @Override
method getVideoId (line 169) | @Override
method getContentType (line 174) | @Override
method getDurationMs (line 179) | @Override
method getBadgeText (line 184) | @Override
method getProductionDate (line 189) | @Override
method getPublishedDate (line 194) | @Override
method getCardImageUrl (line 199) | @Override
method getBackgroundImageUrl (line 204) | @Override
method getWidth (line 209) | @Override
method getHeight (line 214) | @Override
method getChannelId (line 219) | @Override
method getVideoPreviewUrl (line 224) | @Override
method getAudioChannelConfig (line 229) | @Override
method getPurchasePrice (line 234) | @Override
method getRentalPrice (line 239) | @Override
method getRatingStyle (line 244) | @Override
method getRatingScore (line 249) | @Override
method hasUploads (line 254) | @Override
method getClickTrackingParams (line 259) | @Override
method getSearchQuery (line 264) | @Override
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/data/Video.java
class Video (line 34) | public final class Video {
method Video (line 104) | public Video() {
method Video (line 108) | private Video(
method from (line 127) | public static Video from(MediaItem item) {
method from (line 165) | public static Video from(Video item) {
method from (line 195) | public static Video from(String videoId) {
method from (line 201) | public static Video from(ChapterItem chapter) {
method from (line 211) | public static Video from(ItemGroup group) {
method from (line 219) | public static Video from(Item channel) {
method equals (line 240) | @Override
method hashCode (line 254) | @Override
method printDebugInfo (line 261) | public static void printDebugInfo(Context context, Video item) {
method equals (line 268) | public static boolean equals(Video video1, Video video2) {
method isEmpty (line 276) | public static boolean isEmpty(Video video) {
method getId (line 280) | public int getId() {
method getTitle (line 288) | public String getTitle() {
method getTitleFull (line 292) | public String getTitleFull() {
method getSecondTitle (line 296) | public CharSequence getSecondTitle() {
method getSecondTitleFull (line 300) | public CharSequence getSecondTitleFull() {
method getPlaylistId (line 305) | public String getPlaylistId() {
method getCardImageUrl (line 309) | public String getCardImageUrl() {
method getAuthor (line 313) | public String getAuthor() {
method getGroup (line 323) | public VideoGroup getGroup() {
method setGroup (line 327) | public void setGroup(VideoGroup group) {
method getPositionInsideGroup (line 331) | public int getPositionInsideGroup() {
method extractAuthor (line 335) | private static String extractAuthor(CharSequence secondTitle) {
method extractAuthor (line 339) | private static String extractAuthor(String secondTitle) {
method findVideosByAuthor (line 359) | public static List<Video> findVideosByAuthor(VideoGroup group, String ...
method describeContents (line 373) | public int describeContents() {
method fromString (line 377) | public static Video fromString(String spec) {
method toString (line 478) | @NonNull
method hasVideo (line 486) | public boolean hasVideo() {
method hasChannel (line 490) | public boolean hasChannel() {
method hasPlaylist (line 497) | public boolean hasPlaylist() {
method hasNextPlaylist (line 505) | public boolean hasNextPlaylist() {
method hasReloadPageKey (line 512) | public boolean hasReloadPageKey() {
method hasNextPageKey (line 516) | public boolean hasNextPageKey() {
method hasNextItem (line 520) | public boolean hasNextItem() {
method hasNestedItems (line 524) | public boolean hasNestedItems() {
method hasPlaylistIndex (line 528) | public boolean hasPlaylistIndex() {
method isChannel (line 532) | public boolean isChannel() {
method isPlaylistAsChannel (line 539) | public boolean isPlaylistAsChannel() {
method isBadgePlaylistInChannel (line 546) | public boolean isBadgePlaylistInChannel() {
method isMix (line 550) | public boolean isMix() {
method isFullLive (line 556) | public boolean isFullLive() {
method isEmpty (line 560) | public boolean isEmpty() {
method getGroupTitle (line 569) | public String getGroupTitle() {
method getReloadPageKey (line 576) | public String getReloadPageKey() {
method getNextPageKey (line 581) | public String getNextPageKey() {
method getBackgroundUrl (line 585) | public String getBackgroundUrl() {
method belongsToSameAuthorGroup (line 589) | public boolean belongsToSameAuthorGroup() {
method belongsToSamePlaylistGroup (line 603) | public boolean belongsToSamePlaylistGroup() {
method checkAllVideosHasPlaylist (line 624) | private boolean checkAllVideosHasPlaylist() {
method belongsToHome (line 632) | public boolean belongsToHome() {
method belongsToChannel (line 636) | public boolean belongsToChannel() {
method belongsToChannelUploads (line 640) | public boolean belongsToChannelUploads() {
method belongsToSubscriptions (line 644) | public boolean belongsToSubscriptions() {
method belongsToHistory (line 648) | public boolean belongsToHistory() {
method belongsToMusic (line 652) | public boolean belongsToMusic() {
method belongsToShorts (line 656) | public boolean belongsToShorts() {
method belongsToShortsGroup (line 660) | public boolean belongsToShortsGroup() {
method belongsToSearch (line 664) | public boolean belongsToSearch() {
method belongsToNotifications (line 668) | public boolean belongsToNotifications() {
method belongsToPlaybackQueue (line 672) | public boolean belongsToPlaybackQueue() {
method belongsToSuggestions (line 676) | public boolean belongsToSuggestions() {
method belongsToUserPlaylists (line 680) | public boolean belongsToUserPlaylists() {
method belongsToUndefined (line 684) | public boolean belongsToUndefined() {
method belongsToBlockedChannels (line 688) | public boolean belongsToBlockedChannels() {
method getChannelIdOrName (line 698) | public String getChannelIdOrName() {
method belongsToGroup (line 709) | private boolean belongsToGroup(int groupId) {
method belongsToSection (line 713) | public boolean belongsToSection() {
method sync (line 717) | public void sync(Video video) {
method sync (line 725) | public void sync(MediaItemMetadata metadata) {
method sync (line 760) | public void sync(MediaItemFormatInfo formatInfo) {
method sync (line 781) | public void sync(DislikeData dislikeData) {
method copy (line 799) | public Video copy() {
method findNextVideo (line 826) | private MediaItem findNextVideo(MediaItemMetadata metadata) {
method markFullyViewed (line 846) | public void markFullyViewed() {
method markNotViewed (line 851) | public void markNotViewed() {
method getLiveDurationMs (line 856) | public long getLiveDurationMs() {
method getDurationMs (line 872) | public long getDurationMs() {
method getPositionMs (line 876) | public long getPositionMs() {
method getPositionFromPercentWatched (line 884) | private long getPositionFromPercentWatched() {
method toMediaItem (line 894) | public MediaItem toMediaItem() {
method sync (line 898) | public void sync(VideoStateService.State state) {
method isSectionPlaylistEnabled (line 917) | public boolean isSectionPlaylistEnabled(Context context) {
method createPlaylistTitle (line 923) | public String createPlaylistTitle() {
method createChannelTitle (line 936) | public String createChannelTitle() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/data/VideoGroup.java
class VideoGroup (line 18) | public class VideoGroup {
method from (line 45) | public static VideoGroup from(BrowseSection section) {
method from (line 49) | public static VideoGroup from(MediaGroup mediaGroup) {
method from (line 53) | public static VideoGroup from(BrowseSection section, int groupPosition) {
method from (line 57) | public static VideoGroup from(MediaGroup mediaGroup, BrowseSection sec...
method from (line 61) | public static VideoGroup from(Video item) {
method from (line 65) | public static VideoGroup from(Video item, int groupPosition) {
method from (line 69) | public static VideoGroup from(List<Video> items) {
method from (line 73) | public static VideoGroup from(List<Video> items, BrowseSection section) {
method from (line 77) | public static VideoGroup from(List<Video> items, BrowseSection section...
method from (line 99) | public static VideoGroup from(MediaGroup mediaGroup, BrowseSection sec...
method from (line 129) | public static VideoGroup from(VideoGroup baseGroup, MediaGroup mediaGr...
method from (line 152) | public static VideoGroup from(VideoGroup baseGroup, VideoGroup newGrou...
method fromChapters (line 173) | public static VideoGroup fromChapters(List<ChapterItem> chapters, Stri...
method getVideos (line 187) | public List<Video> getVideos() {
method getTitle (line 193) | public String getTitle() {
method setTitle (line 200) | public void setTitle(String title) {
method getId (line 208) | public int getId() {
method setId (line 212) | public void setId(int id) {
method getMediaGroup (line 216) | public MediaGroup getMediaGroup() {
method getSection (line 220) | public BrowseSection getSection() {
method isShorts (line 224) | public boolean isShorts() {
method getPosition (line 241) | public int getPosition() {
method setPosition (line 245) | public void setPosition(int position) {
method getAction (line 249) | public int getAction() {
method setAction (line 253) | public void setAction(int action) {
method getType (line 261) | public int getType() {
method setType (line 265) | public void setType(int type) {
method getReloadPageKey (line 269) | public String getReloadPageKey() {
method getNextPageKey (line 273) | public String getNextPageKey() {
method copy (line 280) | public VideoGroup copy() {
method findTopmostItemWithGroup (line 292) | private static Video findTopmostItemWithGroup(List<Video> items) {
method extractGroupPosition (line 307) | private static int extractGroupPosition(List<Video> items) {
method extractGroupPosition (line 315) | private static int extractGroupPosition(Video item) {
method removeAllBefore (line 325) | public void removeAllBefore(Video video) {
method removeAllBefore (line 333) | public void removeAllBefore(int index) {
method stripPlaylistInfo (line 348) | public void stripPlaylistInfo() {
method findVideoById (line 359) | public Video findVideoById(String videoId) {
method clear (line 376) | public void clear() {
method contains (line 384) | public boolean contains(Video video) {
method getSize (line 392) | public int getSize() {
method indexOf (line 400) | public int indexOf(Video video) {
method get (line 408) | public Video get(int idx) {
method remove (line 416) | public void remove(Video video) {
method isEmpty (line 429) | public boolean isEmpty() {
method add (line 439) | public void add(Video video) {
method add (line 452) | public void add(int idx, Video video) {
method isChannelBlocked (line 474) | private boolean isChannelBlocked(Video video) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/errors/CategoryEmptyError.java
class CategoryEmptyError (line 12) | public class CategoryEmptyError implements ErrorFragmentData {
method CategoryEmptyError (line 16) | public CategoryEmptyError(Context context, @Nullable Throwable error) {
method onAction (line 21) | @Override
method getMessage (line 26) | @Override
method getActionText (line 37) | @Override
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/errors/ErrorFragmentData.java
type ErrorFragmentData (line 3) | public interface ErrorFragmentData {
method onAction (line 4) | void onAction();
method getMessage (line 5) | String getMessage();
method getActionText (line 6) | String getActionText();
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/errors/PasswordError.java
class PasswordError (line 7) | public class PasswordError implements ErrorFragmentData {
method PasswordError (line 10) | public PasswordError(Context context) {
method onAction (line 14) | @Override
method getMessage (line 19) | @Override
method getActionText (line 24) | @Override
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/errors/SignInError.java
class SignInError (line 7) | public class SignInError implements ErrorFragmentData {
method SignInError (line 10) | public SignInError(Context context) {
method onAction (line 14) | @Override
method getMessage (line 19) | @Override
method getActionText (line 24) | @Override
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/BasePlayerController.java
class BasePlayerController (line 38) | public abstract class BasePlayerController implements PlayerEventListener {
method setMainController (line 77) | public void setMainController(PlaybackPresenter mainController) {
method getMainController (line 81) | protected PlayerEventListener getMainController() {
method getController (line 85) | protected <T extends PlayerEventListener> T getController(Class<T> cla...
method getPlayer (line 89) | @Nullable
method getVideo (line 94) | @Nullable
method setAltContext (line 99) | protected void setAltContext(Context context) {
method getContext (line 103) | public Context getContext() {
method getActivity (line 107) | public Activity getActivity() {
method onInit (line 111) | @Override
method onNewVideo (line 116) | @Override
method onSuggestionItemClicked (line 121) | @Override
method onSuggestionItemLongClicked (line 126) | @Override
method onScrollEnd (line 131) | @Override
method onPreviousClicked (line 136) | @Override
method onNextClicked (line 142) | @Override
method onViewCreated (line 148) | @Override
method onViewDestroyed (line 153) | @Override
method onViewPaused (line 158) | @Override
method onViewResumed (line 163) | @Override
method onFinish (line 168) | @Override
method onSourceChanged (line 173) | @Override
method onVideoLoaded (line 178) | @Override
method onEngineInitialized (line 183) | @Override
method onEngineReleased (line 188) | @Override
method onEngineError (line 193) | @Override
method onPlay (line 198) | @Override
method onPause (line 203) | @Override
method onPlayClicked (line 208) | @Override
method onPauseClicked (line 213) | @Override
method onSeekEnd (line 218) | @Override
method onSeekPositionChanged (line 223) | @Override
method onSpeedChanged (line 228) | @Override
method onPlayEnd (line 233) | @Override
method onBuffering (line 238) | @Override
method onControlsShown (line 243) | @Override
method onKeyDown (line 248) | @Override
method onTrackSelected (line 254) | @Override
method onTrackChanged (line 259) | @Override
method onButtonClicked (line 264) | @Override
method onButtonLongClicked (line 269) | @Override
method onTickle (line 274) | @Override
method onMetadata (line 279) | @Override
method getPlayerData (line 284) | protected PlayerData getPlayerData() {
method getGeneralData (line 288) | protected GeneralData getGeneralData() {
method getMediaServiceData (line 292) | protected MediaServiceData getMediaServiceData() {
method getPlayerTweaksData (line 296) | protected PlayerTweaksData getPlayerTweaksData() {
method getRemoteControlData (line 300) | protected RemoteControlData getRemoteControlData() {
method getStateService (line 304) | protected VideoStateService getStateService() {
method getSponsorBlockData (line 308) | protected SponsorBlockData getSponsorBlockData() {
method getSearchData (line 312) | protected SearchData getSearchData() {
method getMainUIData (line 316) | protected MainUIData getMainUIData() {
method getServiceManager (line 320) | protected MediaServiceManager getServiceManager() {
method getViewManager (line 324) | protected ViewManager getViewManager() {
method getAppDialogPresenter (line 328) | protected AppDialogPresenter getAppDialogPresenter() {
method getCommentsService (line 332) | protected CommentsService getCommentsService() {
method getContentService (line 336) | protected ContentService getContentService() {
method getSignInService (line 340) | protected SignInService getSignInService() {
method getNotificationsService (line 344) | protected NotificationsService getNotificationsService() {
method getMediaItemService (line 348) | protected MediaItemService getMediaItemService() {
method getSearchPresenter (line 352) | protected SearchPresenter getSearchPresenter() {
method getPlaybackPresenter (line 356) | protected PlaybackPresenter getPlaybackPresenter() {
method isEmbedPlayer (line 360) | protected boolean isEmbedPlayer() {
method getScreensaverManager (line 364) | protected ScreensaverManager getScreensaverManager() {
method fitVideoIntoDialog (line 373) | protected void fitVideoIntoDialog() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/AutoFrameRateController.java
class AutoFrameRateController (line 28) | public class AutoFrameRateController extends BasePlayerController implem...
method AutoFrameRateController (line 49) | public AutoFrameRateController() {
method onInit (line 56) | @Override
method onViewResumed (line 63) | @Override
method onVideoLoaded (line 73) | @Override
method onModeStart (line 82) | @Override
method onModeError (line 101) | @Override
method onModeCancel (line 116) | @Override
method onEngineReleased (line 121) | @Override
method applyAfrStopDelayed (line 128) | private void applyAfrStopDelayed() {
method applyAfrStop (line 132) | private void applyAfrStop() {
method onFpsCorrectionClick (line 137) | private void onFpsCorrectionClick() {
method onResolutionSwitchClick (line 141) | private void onResolutionSwitchClick() {
method onDoubleRefreshRateClick (line 145) | private void onDoubleRefreshRateClick() {
method onSkip24RateClick (line 149) | public void onSkip24RateClick() {
method applyAfrWrapper (line 153) | private void applyAfrWrapper() {
method applyAfrDelayed (line 162) | private void applyAfrDelayed() {
method applyAfr (line 166) | public void applyAfr() {
method restoreAfr (line 177) | private void restoreAfr() {
method applyAfr (line 184) | private void applyAfr(FormatItem videoFormat, boolean force) {
method maybePausePlayback (line 198) | private void maybePausePlayback() {
method savePlayback (line 213) | private void savePlayback() {
method restorePlayback (line 221) | private void restorePlayback() {
method addUiOptions (line 230) | private void addUiOptions() {
method createAutoFrameRateCategory (line 268) | public static OptionCategory createAutoFrameRateCategory(Context conte...
method createAutoFrameRateCategory (line 272) | private static OptionCategory createAutoFrameRateCategory(Context cont...
method createAutoFrameRatePauseCategory (line 324) | public static OptionCategory createAutoFrameRatePauseCategory(Context ...
method createAutoFrameRateModesCategory (line 343) | public static OptionCategory createAutoFrameRateModesCategory(Context ...
method skipAfr (line 360) | private boolean skipAfr() {
method isSkipShortsPrefs (line 369) | private boolean isSkipShortsPrefs() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/ChatController.java
class ChatController (line 22) | public class ChatController extends BasePlayerController {
method onInit (line 32) | @Override
method onMetadata (line 37) | @Override
method openLiveChat (line 50) | private void openLiveChat() {
method onButtonClicked (line 76) | @Override
method onButtonLongClicked (line 85) | @Override
method onEngineReleased (line 123) | @Override
method onFinish (line 128) | @Override
method disposeActions (line 133) | private void disposeActions() {
method checkItem (line 140) | private boolean checkItem(ChatItem chatItem) {
method enableLiveChat (line 156) | private void enableLiveChat(boolean enabled) {
method placeChatLeft (line 169) | private void placeChatLeft(boolean left) {
method isChatPlacedLeft (line 177) | private boolean isChatPlacedLeft() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/CommentsController.java
class CommentsController (line 22) | public class CommentsController extends BasePlayerController {
method CommentsController (line 30) | public CommentsController() {
method CommentsController (line 33) | public CommentsController(Context context, MediaItemMetadata metadata) {
method onMetadata (line 39) | @Override
method openCommentsDialog (line 49) | private void openCommentsDialog() {
method onButtonClicked (line 124) | @Override
method onEngineReleased (line 137) | @Override
method onFinish (line 143) | @Override
method disposeActions (line 148) | private void disposeActions() {
method loadComments (line 152) | private void loadComments(CommentsReceiver receiver, String commentsKe...
method showDialog (line 165) | private void showDialog(CommentsReceiver receiver, String title) {
method toggleLike (line 173) | private void toggleLike(CommentsReceiver receiver, CommentItem comment...
class MyCommentItem (line 183) | private static final class MyCommentItem implements CommentItem {
method MyCommentItem (line 195) | private MyCommentItem(
method getId (line 210) | @Override
method getMessage (line 215) | @Override
method getAuthorName (line 220) | @Override
method getAuthorPhoto (line 225) | @Override
method getPublishedDate (line 230) | @Override
method getNestedCommentsKey (line 235) | @Override
method isLiked (line 240) | @Override
method setLiked (line 245) | public void setLiked(boolean isLiked) {
method getLikeCount (line 263) | @Override
method getReplyCount (line 268) | @Override
method isEmpty (line 273) | @Override
method from (line 278) | public static MyCommentItem from(CommentItem commentItem) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/HQDialogController.java
class HQDialogController (line 19) | public class HQDialogController extends BasePlayerController {
method onInit (line 29) | @Override
method onViewResumed (line 34) | @Override
method onButtonClicked (line 39) | @Override
method onHighQualityClicked (line 46) | private void onHighQualityClicked() {
method addQualityCategories (line 66) | private void addQualityCategories() {
method selectFormatOption (line 89) | private void selectFormatOption(OptionItem option) {
method persistFormat (line 113) | private void persistFormat(FormatItem formatItem) {
method addVideoBufferCategory (line 125) | private void addVideoBufferCategory() {
method addAudioDelayCategory (line 133) | private void addAudioDelayCategory() {
method addPitchEffectCategory (line 141) | private void addPitchEffectCategory() {
method addSleepTimerCategory (line 145) | private void addSleepTimerCategory() {
method addAudioLanguage (line 149) | private void addAudioLanguage() {
method addNetworkEngine (line 157) | private void addNetworkEngine() {
method onDialogHide (line 165) | private void onDialogHide() {
method addPresetsCategory (line 188) | private void addPresetsCategory() {
method addVideoZoomCategory (line 208) | private void addVideoZoomCategory() {
method removeCategoryInt (line 219) | private void removeCategoryInt(int id) {
method addCategoryInt (line 223) | private void addCategoryInt(OptionCategory category) {
method removeCategory (line 227) | public void removeCategory(int id) {
method addCategory (line 231) | public void addCategory(OptionCategory category) {
method addOnDialogHide (line 235) | public void addOnDialogHide(Runnable listener) {
method removeOnDialogHide (line 239) | public void removeOnDialogHide(Runnable listener) {
method appendOptions (line 243) | private void appendOptions(Map<Integer, OptionCategory> categories) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/PlayerUIController.java
class PlayerUIController (line 51) | public class PlayerUIController extends BasePlayerController {
method PlayerUIController (line 88) | public PlayerUIController() {
method onInit (line 95) | @Override
method onNewVideo (line 108) | @Override
method onControlsShown (line 118) | @Override
method onKeyDown (line 127) | @Override
method onSubtitleClicked (line 149) | private void onSubtitleClicked(int buttonState) {
method onSubtitleLongClicked (line 189) | private void onSubtitleLongClicked() {
method onPlaylistAddClicked (line 249) | private void onPlaylistAddClicked() {
method onDebugInfoClicked (line 261) | private void onDebugInfoClicked(int buttonState) {
method onEngineInitialized (line 273) | @Override
method onVideoLoaded (line 299) | @Override
method onSeekEnd (line 309) | @Override
method onViewResumed (line 318) | @Override
method onViewPaused (line 337) | @Override
method resetButtonStates (line 348) | private void resetButtonStates() {
method onEngineReleased (line 363) | @Override
method onMetadata (line 371) | @Override
method onSuggestionItemLongClicked (line 389) | @Override
method onDislikeClicked (line 420) | private void onDislikeClicked(int buttonState) {
method onLikeClicked (line 446) | private void onLikeClicked(int buttonState) {
method onSeekInterval (line 473) | private void onSeekInterval() {
method onVideoInfoClicked (line 483) | private void onVideoInfoClicked() {
method onShareLink (line 513) | private void onShareLink() {
method onSearchClicked (line 532) | private void onSearchClicked() {
method onVideoZoom (line 537) | private void onVideoZoom() {
method onPipClicked (line 562) | private void onPipClicked() {
method onButtonClicked (line 572) | @Override
method onButtonLongClicked (line 623) | @Override
method disableUiAutoHideTimeout (line 640) | private void disableUiAutoHideTimeout() {
method enableUiAutoHideTimeout (line 645) | private void enableUiAutoHideTimeout() {
method disableSuggestionsResetTimeout (line 653) | private void disableSuggestionsResetTimeout() {
method enableSuggestionsResetTimeout (line 658) | private void enableSuggestionsResetTimeout() {
method disposeTimeouts (line 666) | private void disposeTimeouts() {
method callMediaItemObservable (line 671) | private void callMediaItemObservable(MediaItemObservable callable) {
method handleBackKey (line 684) | private boolean handleBackKey(int keyCode) {
method handleMenuKey (line 708) | private boolean handleMenuKey(int keyCode) {
method handleConfirmKey (line 723) | private boolean handleConfirmKey(int keyCode) {
method handleStopKey (line 752) | private boolean handleStopKey(int keyCode) {
method handleNumKeys (line 763) | private boolean handleNumKeys(int keyCode) {
method handlePlayPauseKey (line 776) | private boolean handlePlayPauseKey(int keyCode) {
method handleLeftRightSkip (line 786) | private boolean handleLeftRightSkip(int keyCode) {
method handleUpDownSkip (line 806) | private boolean handleUpDownSkip(int keyCode) {
type MediaItemObservable (line 826) | private interface MediaItemObservable {
method call (line 827) | Observable<Void> call(MediaItem item);
method setPlaylistAddButtonStateCached (line 830) | private void setPlaylistAddButtonStateCached() {
method setPlaylistAddButtonState (line 848) | private void setPlaylistAddButtonState() {
method setSubtitleButtonState (line 864) | private void setSubtitleButtonState() {
method startTempBackgroundMode (line 872) | private void startTempBackgroundMode(Class<?> clazz) {
method isSubtitleSelected (line 880) | private boolean isSubtitleSelected() {
method isSubtitleEnabled (line 903) | private boolean isSubtitleEnabled() {
method enableSubtitleForChannel (line 907) | private void enableSubtitleForChannel(boolean enable) {
method getChannelId (line 920) | private String getChannelId() {
method applyScreenOff (line 924) | private void applyScreenOff(int buttonState) {
method applyScreenOffTimeout (line 946) | private void applyScreenOffTimeout(int buttonState) {
method prepareScreenOff (line 957) | private void prepareScreenOff() {
method onRotate (line 973) | private void onRotate() {
method onFlip (line 985) | private void onFlip() {
method onSubscribe (line 997) | private void onSubscribe(int buttonState) {
method applySoundOff (line 1017) | private void applySoundOff(int buttonState) {
method applySoundOffButtonState (line 1034) | private void applySoundOffButtonState() {
method applyAfr (line 1041) | private void applyAfr(int buttonState) {
method applyRepeatMode (line 1051) | private void applyRepeatMode(int buttonState) {
method showPlaybackModeDialog (line 1062) | private void showPlaybackModeDialog() {
method getNextRepeatMode (line 1077) | private int getNextRepeatMode(int buttonState) {
method reorderSubtitles (line 1084) | private void reorderSubtitles(List<FormatItem> subtitleFormats) {
method showNotificationsDialog (line 1107) | private void showNotificationsDialog() {
method showScreenOffDialog (line 1130) | private void showScreenOffDialog() {
method showSoundOffDialog (line 1147) | private void showSoundOffDialog() {
method openChannel (line 1159) | private void openChannel() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/RemoteController.java
class RemoteController (line 29) | public class RemoteController extends BasePlayerController implements On...
method RemoteController (line 46) | public RemoteController(Context context) {
method onDataChange (line 55) | @Override
method onNewVideo (line 60) | @Override
method onInit (line 68) | @Override
method onViewResumed (line 73) | @Override
method onVideoLoaded (line 78) | @Override
method onPlay (line 95) | @Override
method onPause (line 100) | @Override
method onPlayEnd (line 105) | @Override
method onTrackSelected (line 120) | @Override
method onEngineReleased (line 132) | @Override
method onFinish (line 140) | @Override
method postStartPlaying (line 146) | private void postStartPlaying(@Nullable Video item, int state) {
method postStartPlaying (line 164) | private void postStartPlaying(String videoId, long positionMs, long du...
method postState (line 176) | private void postState(long positionMs, long durationMs, int state) {
method postVolumeChange (line 188) | private void postVolumeChange(int volume) {
method postSubtitleChange (line 200) | private void postSubtitleChange(String vssId, String languageCode) {
method postPlayState (line 211) | private void postPlayState(int state) {
method postSeek (line 219) | private void postSeek(long positionMs) {
method postIdle (line 223) | private void postIdle() {
method tryListening (line 227) | private void tryListening() {
method startListening (line 235) | private void startListening() {
method startListeningInt (line 243) | private void startListeningInt() {
method stopListening (line 265) | private void stopListening() {
method processCommand (line 271) | private void processCommand(Command command) {
method openNewVideo (line 513) | private void openNewVideo(Video newVideo) {
method movePlayerToForeground (line 526) | private void movePlayerToForeground() {
method registerVolumeObserver (line 535) | private void registerVolumeObserver() {
method unregisterVolumeObserver (line 553) | private void unregisterVolumeObserver() {
method isConnectedBefore (line 560) | private boolean isConnectedBefore() {
method isRemoteDisabled (line 564) | private boolean isRemoteDisabled() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/SponsorBlockController.java
class SponsorBlockController (line 32) | public class SponsorBlockController extends BasePlayerController {
class SegmentAction (line 45) | public static class SegmentAction {
method from (line 49) | public static SegmentAction from(String spec) {
method from (line 66) | public static SegmentAction from(String name, int action) {
method toString (line 74) | @NonNull
method onInit (line 81) | @Override
method onNewVideo (line 87) | @Override
method onVideoLoaded (line 95) | @Override
method onMetadata (line 111) | @Override
method onEngineReleased (line 123) | @Override
method onButtonClicked (line 128) | @Override
method onButtonLongClicked (line 141) | @Override
method checkVideo (line 152) | private boolean checkVideo(Video video) {
method updateSponsorSegmentsAndWatch (line 157) | private void updateSponsorSegmentsAndWatch(Video item) {
method startSponsorWatcher (line 180) | private Observable<Long> startSponsorWatcher(List<SponsorSegment> segm...
method disposeActions (line 202) | private void disposeActions() {
method skipSegment (line 212) | private void skipSegment(long interval) {
method isPositionInsideSegment (line 235) | private boolean isPositionInsideSegment(long positionMs, SponsorSegmen...
method simpleSkip (line 248) | private void simpleSkip(long skipPosMs) {
method messageSkip (line 257) | private void messageSkip(long skipPosMs, String category) {
method confirmSkip (line 268) | private void confirmSkip(long skipPosMs, String category) {
method toSeekBarSegments (line 301) | private List<SeekBarSegment> toSeekBarSegments(List<SponsorSegment> se...
method setPositionMs (line 328) | private void setPositionMs(long positionMs) {
method findMatchedSegments (line 338) | private List<SponsorSegment> findMatchedSegments(long positionMs, List...
method applyActions (line 370) | private void applyActions(List<SponsorSegment> foundSegments) {
method closeTransparentDialog (line 402) | private void closeTransparentDialog() {
method isChannelExcluded (line 410) | private boolean isChannelExcluded(String channelId) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/SuggestionsController.java
class SuggestionsController (line 40) | public class SuggestionsController extends BasePlayerController {
type OnVideoGroup (line 54) | private interface OnVideoGroup {
method onVideoGroup (line 55) | void onVideoGroup(VideoGroup group);
type OnMetadata (line 58) | private interface OnMetadata {
method onMetadata (line 59) | void onMetadata(MediaItemMetadata metadata);
method onInit (line 62) | @Override
method onNewVideo (line 69) | @Override
method onVideoLoaded (line 81) | @Override
method onEngineReleased (line 92) | @Override
method onFinish (line 97) | @Override
method onScrollEnd (line 102) | @Override
method onSuggestionItemClicked (line 114) | @Override
method onControlsShown (line 119) | @Override
method onSeekEnd (line 128) | @Override
method onSeekPositionChanged (line 141) | @Override
method onTickle (line 148) | @Override
method updateLiveDescription (line 153) | private void updateLiveDescription() {
method continueGroup (line 167) | private void continueGroup(VideoGroup group) {
method continueGroup (line 171) | private void continueGroup(VideoGroup group, boolean showLoading) {
method continueGroup (line 175) | private void continueGroup(VideoGroup group, OnVideoGroup callback, bo...
method syncCurrentVideo (line 222) | private void syncCurrentVideo(MediaItemMetadata mediaItemMetadata, Vid...
method loadSuggestions (line 241) | public void loadSuggestions(Video video) {
method loadMetadata (line 250) | private void loadMetadata(Video video, OnMetadata callback) {
method getNext (line 281) | public Video getNext() {
method getPrevious (line 298) | public Video getPrevious() {
method getPreviousFromGroup (line 313) | private Video getPreviousFromGroup(Video current) {
method clearSuggestionsIfNeeded (line 338) | private void clearSuggestionsIfNeeded(Video video) {
method updateSuggestions (line 349) | private void updateSuggestions(MediaItemMetadata mediaItemMetadata, Vi...
method appendSuggestions (line 358) | private void appendSuggestions(Video video, MediaItemMetadata mediaIte...
method mergePlaybackAndRemoteQueueIfNeeded (line 428) | private void mergePlaybackAndRemoteQueueIfNeeded(Video video, MediaIte...
method mergeUserAndRemoteQueue (line 449) | private void mergeUserAndRemoteQueue(VideoGroup videoGroup) {
method appendPlaybackQueueIfNeeded (line 460) | private void appendPlaybackQueueIfNeeded() {
method appendRemoteQueueIfNeeded (line 478) | private void appendRemoteQueueIfNeeded(Video video, VideoGroup remoteG...
method addChapterMarkersIfNeeded (line 505) | private void addChapterMarkersIfNeeded() {
method appendChapterSuggestionsIfNeeded (line 513) | private void appendChapterSuggestionsIfNeeded() {
method startChapterNotificationServiceIfNeeded (line 523) | private void startChapterNotificationServiceIfNeeded() {
method startChapterNotificationServiceIfNeededInt (line 529) | private void startChapterNotificationServiceIfNeededInt() {
method appendChaptersIfNeeded (line 548) | private void appendChaptersIfNeeded(MediaItemMetadata mediaItemMetadat...
method appendSectionPlaylistIfNeeded (line 557) | private void appendSectionPlaylistIfNeeded(Video video) {
method markAsQueueIfNeeded (line 572) | private void markAsQueueIfNeeded(Video item) {
method focusCurrentChapter (line 580) | private void focusCurrentChapter() {
method updateSeekPreviewTitle (line 599) | private void updateSeekPreviewTitle(long positionMs) {
method toSeekBarSegments (line 611) | private List<SeekBarSegment> toSeekBarSegments(List<ChapterItem> chapt...
method continueGroupIfNeeded (line 639) | private void continueGroupIfNeeded(VideoGroup group) {
method focusAndContinueIfNeeded (line 649) | private void focusAndContinueIfNeeded(VideoGroup group) {
method focusAndContinueIfNeeded (line 653) | private void focusAndContinueIfNeeded(VideoGroup group, Runnable onDon...
method findNextSectionVideoIfNeeded (line 685) | private void findNextSectionVideoIfNeeded(Video video) {
method findRandomSectionVideo (line 693) | private void findRandomSectionVideo(Video video) {
method findNextSectionVideo (line 710) | private void findNextSectionVideo(Video video) {
method showChapterDialog (line 743) | private void showChapterDialog(ChapterItem chapter) {
method getNextChapter (line 781) | private ChapterItem getNextChapter() {
method getCurrentChapter (line 796) | private Pair<ChapterItem, Integer> getCurrentChapter() {
method getCurrentChapter (line 804) | private Pair<ChapterItem, Integer> getCurrentChapter(long positionMs) {
method callListener (line 823) | private void callListener(MediaItemMetadata mediaItemMetadata) {
method disposeActions (line 829) | private void disposeActions() {
method appendDislikes (line 838) | private void appendDislikes(Video video) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/VideoLoaderController.java
class VideoLoaderController (line 38) | public class VideoLoaderController extends BasePlayerController {
method VideoLoaderController (line 80) | public VideoLoaderController() {
method onInit (line 84) | @Override
method onNewVideo (line 90) | @Override
method onBuffering (line 110) | @Override
method onSeekEnd (line 115) | @Override
method onLongBuffering (line 121) | private void onLongBuffering() {
method onEngineInitialized (line 146) | @Override
method onEngineReleased (line 158) | @Override
method onEngineError (line 163) | @Override
method onVideoLoaded (line 171) | @Override
method onPreviousClicked (line 183) | @Override
method onNextClicked (line 190) | @Override
method loadPrevious (line 201) | public void loadPrevious() {
method loadNext (line 213) | public void loadNext() {
method onPlayEnd (line 232) | @Override
method onSuggestionItemClicked (line 247) | @Override
method onKeyDown (line 255) | @Override
method onTickle (line 269) | @Override
method checkSleepTimer (line 274) | private void checkSleepTimer() {
method loadVideo (line 291) | private void loadVideo(Video item) {
method loadSuggestions (line 303) | private void loadSuggestions(Video item) {
method waitMetadataSync (line 311) | private void waitMetadataSync(Video current, boolean showLoadingMsg) {
method loadFormatInfo (line 331) | private void loadFormatInfo(Video video) {
method processFormatInfo (line 349) | private void processFormatInfo(MediaItemFormatInfo formatInfo) {
method scheduleReloadVideoTimer (line 418) | private void scheduleReloadVideoTimer(int delayMs) {
method scheduleNextVideoTimer (line 430) | private void scheduleNextVideoTimer(int delayMs) {
method scheduleRebootAppTimer (line 442) | private void scheduleRebootAppTimer(int delayMs) {
method scheduleRestartEngineTimer (line 450) | private void scheduleRestartEngineTimer(int delayMs) {
method openVideoInt (line 458) | private void openVideoInt(Video item) {
method isActionsRunning (line 475) | private boolean isActionsRunning() {
method disposeActions (line 479) | private void disposeActions() {
method runFormatErrorAction (line 486) | private void runFormatErrorAction(Throwable error) {
method runEngineErrorAction (line 516) | private void runEngineErrorAction(int type, int rendererIndex, Throwab...
method applyEngineErrorAction (line 538) | private boolean applyEngineErrorAction(int type, int rendererIndex, Th...
method getErrorTitle (line 619) | @SuppressLint("StringFormatMatches")
method restartEngine (line 670) | private void restartEngine() {
method reloadVideo (line 674) | private void reloadVideo() {
method rebootApp (line 678) | private void rebootApp() {
method applyFix (line 682) | private List<String> applyFix(List<String> urlList) {
method applyPlaybackMode (line 691) | private void applyPlaybackMode(int playbackMode) {
method stopPlayback (line 759) | private void stopPlayback() {
method restartPlaylistIfNeeded (line 769) | private void restartPlaylistIfNeeded() {
method acceptAdaptiveFormats (line 784) | private boolean acceptAdaptiveFormats(MediaItemFormatInfo formatInfo) {
method acceptDashLive (line 811) | private boolean acceptDashLive(MediaItemFormatInfo formatInfo) {
method onMetadata (line 819) | @Override
method onPlay (line 824) | @Override
method onPause (line 829) | @Override
method loadRandomNext (line 834) | private void loadRandomNext() {
method loadRandomNext2 (line 869) | private void loadRandomNext2() {
method updateBufferingCountIfNeeded (line 880) | private void updateBufferingCountIfNeeded() {
method updateBufferingCount (line 891) | private void updateBufferingCount() {
method isBufferingRecurrent (line 910) | private boolean isBufferingRecurrent() {
method switchNextEngine (line 914) | private void switchNextEngine() {
method getNextEngine (line 918) | private int getNextEngine() {
method getFasterDataSource (line 926) | private static int getFasterDataSource() {
method enableFasterDataSource (line 933) | private void enableFasterDataSource() {
method isFasterDataSourceEnabled (line 944) | private boolean isFasterDataSourceEnabled() {
method getPlaybackMode (line 949) | private int getPlaybackMode() {
method applyAspectRatio (line 964) | private void applyAspectRatio(MediaItemFormatInfo formatInfo) {
method preloadNextVideoIfNeeded (line 983) | private void preloadNextVideoIfNeeded() {
method isSubtitlesEnabled (line 993) | private boolean isSubtitlesEnabled() {
method disableSubtitles (line 997) | private void disableSubtitles() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/VideoStateController.java
class VideoStateController (line 21) | public class VideoStateController extends BasePlayerController {
method onNewVideo (line 43) | @Override
method onPreviousClicked (line 72) | @Override
method onNextClicked (line 85) | @Override
method onSuggestionItemClicked (line 103) | @Override
method onEngineInitialized (line 110) | @Override
method onEngineReleased (line 125) | @Override
method onTickle (line 138) | @Override
method onMetadata (line 150) | @Override
method onEngineError (line 162) | @Override
method onVideoLoaded (line 174) | @Override
method onPlay (line 189) | @Override
method onPause (line 197) | @Override
method onTrackSelected (line 205) | @Override
method onPlayEnd (line 227) | @Override
method onBuffering (line 235) | @Override
method onSourceChanged (line 244) | @Override
method onSpeedChanged (line 250) | @Override
method onButtonClicked (line 259) | @Override
method onButtonLongClicked (line 266) | @Override
method onSpeedClicked (line 273) | private void onSpeedClicked(boolean enabled) {
method onSpeedLongClicked (line 297) | private void onSpeedLongClicked(boolean enabled) {
method onFinish (line 314) | @Override
method clearStateOfNextVideo (line 319) | private void clearStateOfNextVideo() {
method resetPositionIfNeeded (line 328) | private void resetPositionIfNeeded(Video item) {
method resetGlobalSpeedIfNeeded (line 356) | private void resetGlobalSpeedIfNeeded() {
method resetPosition (line 362) | private void resetPosition(Video video) {
method enableIncognitoIfNeeded (line 379) | private void enableIncognitoIfNeeded(Video item) {
method restoreVideoFormat (line 392) | private void restoreVideoFormat() {
method restoreAudioFormat (line 404) | private void restoreAudioFormat() {
method restoreSubtitleFormat (line 412) | private void restoreSubtitleFormat() {
method saveState (line 427) | private void saveState() {
method restoreState (line 441) | private void restoreState() {
method savePosition (line 464) | private void savePosition() {
method restorePosition (line 494) | private void restorePosition() {
method updateHistory (line 528) | private void updateHistory() {
method restorePendingPosition (line 543) | private void restorePendingPosition() {
method restoreSpeedAndPositionIfNeeded (line 556) | private void restoreSpeedAndPositionIfNeeded() {
method blockPlay (line 583) | public void blockPlay(boolean block) {
method setPlayEnabled (line 587) | public void setPlayEnabled(boolean isPlayEnabled) {
method getPlayEnabled (line 592) | public boolean getPlayEnabled() {
method restoreVolume (line 596) | private void restoreVolume() {
method restorePitch (line 615) | private void restorePitch() {
method restoreFormats (line 623) | private void restoreFormats() {
method showHideScreensaver (line 631) | private void showHideScreensaver(boolean show) {
method isMusicVideo (line 645) | private boolean isMusicVideo() {
method isStateOutdated (line 657) | private boolean isStateOutdated(State state, Video item) {
method syncWithPlaylists (line 673) | private void syncWithPlaylists() {
method isLiveEnd (line 689) | private boolean isLiveEnd() {
method getLiveThreshold (line 697) | private long getLiveThreshold() {
method getLiveBuffer (line 701) | private long getLiveBuffer() {
method isMutedEmbed (line 705) | private boolean isMutedEmbed() {
method isBeginEmbed (line 709) | private boolean isBeginEmbed() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/listener/PlayerEngineEventListener.java
type PlayerEngineEventListener (line 8) | public interface PlayerEngineEventListener {
method onPlay (line 33) | void onPlay();
method onPause (line 34) | void onPause();
method onPlayEnd (line 35) | void onPlayEnd();
method onBuffering (line 36) | void onBuffering();
method onSeekEnd (line 37) | void onSeekEnd();
method onSeekPositionChanged (line 38) | void onSeekPositionChanged(long positionMs);
method onSpeedChanged (line 39) | void onSpeedChanged(float speed);
method onSourceChanged (line 40) | void onSourceChanged(Video item);
method onVideoLoaded (line 41) | void onVideoLoaded(Video item);
method onEngineInitialized (line 42) | void onEngineInitialized();
method onEngineReleased (line 43) | void onEngineReleased();
method onEngineError (line 44) | void onEngineError(int type, int rendererIndex, Throwable error);
method onTrackChanged (line 45) | void onTrackChanged(FormatItem track);
method onTrackSelected (line 46) | void onTrackSelected(FormatItem track);
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/listener/PlayerEventListener.java
type PlayerEventListener (line 8) | public interface PlayerEventListener extends PlayerUiEventListener, Play...
method onNewVideo (line 9) | void onNewVideo(Video item);
method onMetadata (line 10) | void onMetadata(MediaItemMetadata metadata);
method onInit (line 14) | void onInit();
method onFinish (line 15) | void onFinish();
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/listener/PlayerUiEventListener.java
type PlayerUiEventListener (line 5) | public interface PlayerUiEventListener {
method onSuggestionItemClicked (line 6) | void onSuggestionItemClicked(Video item);
method onSuggestionItemLongClicked (line 7) | void onSuggestionItemLongClicked(Video item);
method onScrollEnd (line 8) | void onScrollEnd(Video item);
method onPreviousClicked (line 9) | boolean onPreviousClicked();
method onNextClicked (line 10) | boolean onNextClicked();
method onPlayClicked (line 11) | void onPlayClicked();
method onPauseClicked (line 12) | void onPauseClicked();
method onKeyDown (line 13) | boolean onKeyDown(int keyCode);
method onButtonClicked (line 14) | void onButtonClicked(int buttonId, int buttonState);
method onButtonLongClicked (line 15) | void onButtonLongClicked(int buttonId, int buttonState);
method onControlsShown (line 16) | void onControlsShown(boolean shown);
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/listener/ViewEventListener.java
type ViewEventListener (line 3) | public interface ViewEventListener {
method onViewCreated (line 4) | void onViewCreated();
method onViewDestroyed (line 5) | void onViewDestroyed();
method onViewPaused (line 6) | void onViewPaused();
method onViewResumed (line 7) | void onViewResumed();
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/manager/PlayerConstants.java
type PlayerConstants (line 5) | public interface PlayerConstants {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/manager/PlayerEngine.java
type PlayerEngine (line 9) | public interface PlayerEngine extends PlayerConstants {
method openSabr (line 10) | void openSabr(MediaItemFormatInfo formatInfo);
method openDash (line 11) | void openDash(MediaItemFormatInfo formatInfo);
method openDash (line 12) | void openDash(InputStream dashManifest);
method openDashUrl (line 13) | void openDashUrl(String dashManifestUrl);
method openHlsUrl (line 14) | void openHlsUrl(String hlsPlaylistUrl);
method openUrlList (line 15) | void openUrlList(List<String> urlList);
method openMerged (line 16) | void openMerged(MediaItemFormatInfo formatInfo, String hlsPlaylistUrl);
method openMerged (line 17) | void openMerged(InputStream dashManifest, String hlsPlaylistUrl);
method getPositionMs (line 18) | long getPositionMs();
method setPositionMs (line 19) | void setPositionMs(long positionMs);
method getDurationMs (line 20) | long getDurationMs();
method setPlayWhenReady (line 21) | void setPlayWhenReady(boolean play);
method getPlayWhenReady (line 22) | boolean getPlayWhenReady();
method isPlaying (line 23) | boolean isPlaying();
method isLoading (line 24) | boolean isLoading();
method getVideoFormats (line 25) | List<FormatItem> getVideoFormats();
method getAudioFormats (line 26) | List<FormatItem> getAudioFormats();
method getSubtitleFormats (line 27) | List<FormatItem> getSubtitleFormats();
method setFormat (line 28) | void setFormat(FormatItem option);
method getVideoFormat (line 29) | FormatItem getVideoFormat();
method getAudioFormat (line 30) | FormatItem getAudioFormat();
method getSubtitleFormat (line 31) | FormatItem getSubtitleFormat();
method isEngineInitialized (line 32) | boolean isEngineInitialized();
method restartEngine (line 33) | void restartEngine();
method reloadPlayback (line 34) | void reloadPlayback();
method blockEngine (line 35) | void blockEngine(boolean block);
method isEngineBlocked (line 36) | boolean isEngineBlocked();
method isInPIPMode (line 37) | boolean isInPIPMode();
method containsMedia (line 38) | boolean containsMedia();
method setSpeed (line 39) | void setSpeed(float speed);
method getSpeed (line 40) | float getSpeed();
method setPitch (line 41) | void setPitch(float pitch);
method getPitch (line 42) | float getPitch();
method setVolume (line 43) | void setVolume(float volume);
method getVolume (line 44) | float getVolume();
method setResizeMode (line 45) | void setResizeMode(int mode);
method getResizeMode (line 46) | int getResizeMode();
method setZoomPercents (line 47) | void setZoomPercents(int percents);
method setAspectRatio (line 48) | void setAspectRatio(float ratio);
method setRotationAngle (line 49) | void setRotationAngle(int angle);
method setVideoFlipEnabled (line 50) | void setVideoFlipEnabled(boolean enabled);
method setVideoGravity (line 51) | void setVideoGravity(int gravity);
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/manager/PlayerManager.java
type PlayerManager (line 7) | public interface PlayerManager extends PlayerEngine, PlayerUI {
method setVideo (line 8) | void setVideo(Video item);
method getVideo (line 9) | Video getVideo();
method finish (line 10) | void finish();
method finishReally (line 11) | void finishReally();
method showBackground (line 12) | void showBackground(String url);
method showBackgroundColor (line 13) | void showBackgroundColor(int colorResId);
method resetPlayerState (line 14) | void resetPlayerState();
method isEmbed (line 15) | boolean isEmbed();
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/manager/PlayerUI.java
type PlayerUI (line 10) | public interface PlayerUI {
method updateSuggestions (line 14) | void updateSuggestions(VideoGroup group);
method removeSuggestions (line 15) | void removeSuggestions(VideoGroup group);
method getSuggestionsIndex (line 16) | int getSuggestionsIndex(VideoGroup group);
method getSuggestionsByIndex (line 17) | VideoGroup getSuggestionsByIndex(int index);
method focusSuggestedItem (line 18) | void focusSuggestedItem(int index);
method focusSuggestedItem (line 19) | void focusSuggestedItem(Video video);
method resetSuggestedPosition (line 20) | void resetSuggestedPosition();
method isSuggestionsEmpty (line 21) | boolean isSuggestionsEmpty();
method clearSuggestions (line 22) | void clearSuggestions();
method showOverlay (line 23) | void showOverlay(boolean show);
method isOverlayShown (line 24) | boolean isOverlayShown();
method showSuggestions (line 25) | void showSuggestions(boolean show);
method isSuggestionsShown (line 26) | boolean isSuggestionsShown();
method showControls (line 27) | void showControls(boolean show);
method isControlsShown (line 28) | boolean isControlsShown();
method getButtonState (line 29) | int getButtonState(int buttonId);
method setButtonState (line 30) | void setButtonState(int buttonId, int buttonState);
method setChannelIcon (line 31) | void setChannelIcon(String iconUrl);
method setSeekPreviewTitle (line 32) | void setSeekPreviewTitle(String title);
method setNextTitle (line 33) | void setNextTitle(Video nextVideo);
method showDebugInfo (line 34) | void showDebugInfo(boolean show);
method showSubtitles (line 35) | void showSubtitles(boolean show);
method loadStoryboard (line 36) | void loadStoryboard();
method setTitle (line 37) | void setTitle(String title);
method showProgressBar (line 38) | void showProgressBar(boolean show);
method setSeekBarSegments (line 39) | void setSeekBarSegments(List<SeekBarSegment> segments);
method updateEndingTime (line 40) | void updateEndingTime();
method setChatReceiver (line 41) | void setChatReceiver(ChatReceiver chatReceiver);
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/service/VideoStateService.java
class VideoStateService (line 16) | public class VideoStateService implements ProfileChangeListener {
method VideoStateService (line 32) | private VideoStateService(Context context) {
method instance (line 40) | public static VideoStateService instance(Context context) {
method getStates (line 48) | public List<State> getStates() {
method getLastState (line 52) | public @Nullable State getLastState() {
method getByVideoId (line 60) | public State getByVideoId(String videoId) {
method removeByVideoId (line 70) | public void removeByVideoId(String videoId) {
method isEmpty (line 75) | public boolean isEmpty() {
method save (line 79) | public void save(State state) {
method clear (line 84) | public void clear() {
method setHistoryBroken (line 89) | public void setHistoryBroken(boolean isBroken) {
method isHistoryBroken (line 93) | public boolean isHistoryBroken() {
method getSessionStartTimeMs (line 97) | public long getSessionStartTimeMs() {
method restoreState (line 101) | private void restoreState() {
method persistStateInt (line 112) | private void persistStateInt() {
method persistNow (line 121) | public void persistNow() {
method persistState (line 125) | private void persistState() {
class State (line 130) | public static class State {
method State (line 138) | public State(Video video, long positionMs) {
method State (line 142) | public State(Video video, long positionMs, long durationMs) {
method State (line 146) | public State(Video video, long positionMs, long durationMs, float sp...
method from (line 153) | public static State from(String spec) {
method toString (line 178) | @NonNull
method equals (line 184) | @Override
method onProfileChanged (line 194) | @Override
method setStateDataSafe (line 199) | private void setStateDataSafe(String data) {
method setStateData (line 207) | private void setStateData(String data) {
method getStateData (line 221) | private String getStateData() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/ui/AbstractCommentsReceiver.java
class AbstractCommentsReceiver (line 8) | public abstract class AbstractCommentsReceiver implements CommentsReceiv...
method AbstractCommentsReceiver (line 12) | public AbstractCommentsReceiver(Context context) {
method addCommentGroup (line 16) | @Override
method loadBackup (line 23) | @Override
method sync (line 30) | @Override
method setCallback (line 37) | @Override
method onLoadMore (line 42) | @Override
method onCommentClicked (line 47) | @Override
method onCommentLongClicked (line 52) | @Override
method onFinish (line 57) | @Override
method getLoadingMessage (line 62) | @Override
method getErrorMessage (line 71) | @Override
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/ui/ChatReceiver.java
type ChatReceiver (line 5) | public interface ChatReceiver {
type Callback (line 6) | interface Callback {
method onChatItem (line 7) | void onChatItem(ChatItem chatItem);
method addChatItem (line 9) | void addChatItem(ChatItem chatItem);
method setCallback (line 10) | void setCallback(Callback callback);
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/ui/ChatReceiverImpl.java
class ChatReceiverImpl (line 5) | public class ChatReceiverImpl implements ChatReceiver {
method addChatItem (line 8) | @Override
method setCallback (line 15) | @Override
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/ui/CommentsReceiver.java
type CommentsReceiver (line 6) | public interface CommentsReceiver {
type Callback (line 7) | interface Callback {
method onCommentGroup (line 8) | void onCommentGroup(CommentGroup commentGroup);
method onBackup (line 9) | void onBackup(Backup backup);
method onSync (line 10) | void onSync(CommentItem commentItem);
type Backup (line 12) | interface Backup {}
method addCommentGroup (line 13) | void addCommentGroup(CommentGroup commentGroup);
method loadBackup (line 14) | void loadBackup(Backup backup);
method sync (line 15) | void sync(CommentItem commentItem);
method setCallback (line 16) | void setCallback(Callback callback);
method onLoadMore (line 17) | void onLoadMore(CommentGroup commentGroup);
method onStart (line 18) | void onStart();
method onCommentClicked (line 19) | void onCommentClicked(CommentItem commentItem);
method onCommentLongClicked (line 20) | void onCommentLongClicked(CommentItem commentItem);
method onFinish (line 21) | void onFinish(Backup backup);
method getLoadingMessage (line 22) | String getLoadingMessage();
method getErrorMessage (line 23) | String getErrorMessage();
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/ui/OptionCallback.java
type OptionCallback (line 3) | public interface OptionCallback {
method onSelect (line 4) | void onSelect(OptionItem optionItem);
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/ui/OptionCategory.java
class OptionCategory (line 7) | public class OptionCategory {
method radioList (line 8) | public static OptionCategory radioList(String title, List<OptionItem> ...
method checkedList (line 12) | public static OptionCategory checkedList(String title, List<OptionItem...
method stringList (line 16) | public static OptionCategory stringList(String title, List<OptionItem>...
method longText (line 20) | public static OptionCategory longText(String title, OptionItem item) {
method chat (line 24) | public static OptionCategory chat(String title, OptionItem item) {
method comments (line 28) | public static OptionCategory comments(String title, OptionItem item) {
method singleSwitch (line 32) | public static OptionCategory singleSwitch(OptionItem item) {
method singleButton (line 38) | public static OptionCategory singleButton(OptionItem item) {
method from (line 44) | public static OptionCategory from(int id, int type, String title, List...
method from (line 48) | public static OptionCategory from(int id, int type, String title, Opti...
method OptionCategory (line 52) | private OptionCategory(String title, List<OptionItem> options, int typ...
method OptionCategory (line 56) | private OptionCategory(String title, List<OptionItem> options, int typ...
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/ui/OptionItem.java
type OptionItem (line 3) | public interface OptionItem {
method getId (line 4) | int getId();
method getTitle (line 5) | CharSequence getTitle();
method getDescription (line 6) | CharSequence getDescription();
method isSelected (line 7) | boolean isSelected();
method onSelect (line 8) | void onSelect(boolean isSelected);
method getData (line 9) | Object getData();
method setRequired (line 10) | void setRequired(OptionItem... items);
method getRequired (line 11) | OptionItem[] getRequired();
method setRadio (line 12) | void setRadio(OptionItem... items);
method getRadio (line 13) | OptionItem[] getRadio();
method getChatReceiver (line 14) | ChatReceiver getChatReceiver();
method getCommentsReceiver (line 15) | CommentsReceiver getCommentsReceiver();
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/ui/SeekBarSegment.java
class SeekBarSegment (line 5) | public class SeekBarSegment {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/ui/UiOptionItem.java
class UiOptionItem (line 8) | public class UiOptionItem implements OptionItem {
method from (line 21) | public static List<OptionItem> from(List<FormatItem> formats, OptionCa...
method from (line 25) | public static List<OptionItem> from(List<FormatItem> formats, OptionCa...
method from (line 39) | public static OptionItem from(FormatItem format, OptionCallback callba...
method from (line 43) | public static OptionItem from(FormatItem format, OptionCallback callba...
method from (line 58) | public static OptionItem from(CharSequence title) {
method from (line 62) | public static OptionItem from(CharSequence title, OptionCallback callb...
method from (line 66) | public static OptionItem from(CharSequence title, OptionCallback callb...
method from (line 70) | public static OptionItem from(CharSequence title, CharSequence descrip...
method from (line 74) | public static OptionItem from(CharSequence title, OptionCallback callb...
method from (line 78) | public static OptionItem from(CharSequence title, CharSequence descrip...
method from (line 90) | public static OptionItem from(CharSequence title, ChatReceiver chatRec...
method from (line 98) | public static OptionItem from(CharSequence title, CommentsReceiver com...
method toFormat (line 106) | public static FormatItem toFormat(OptionItem option) {
method getId (line 114) | @Override
method getTitle (line 119) | @Override
method getDescription (line 124) | @Override
method isSelected (line 129) | @Override
method onSelect (line 134) | @Override
method getData (line 143) | @Override
method setRequired (line 148) | @Override
method getRequired (line 157) | @Override
method setRadio (line 162) | @Override
method getRadio (line 171) | @Override
method getChatReceiver (line 176) | @Override
method getCommentsReceiver (line 181) | @Override
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/search/MediaServiceSearchTagProvider.java
class MediaServiceSearchTagProvider (line 13) | public class MediaServiceSearchTagProvider implements SearchTagsProvider {
method MediaServiceSearchTagProvider (line 19) | public MediaServiceSearchTagProvider(boolean ignoreEmptyQuery) {
method search (line 25) | @Override
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/search/PrefsSearchTagsProvider.java
class PrefsSearchTagsProvider (line 8) | public class PrefsSearchTagsProvider implements SearchTagsProvider {
method search (line 9) | @Override
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/search/SearchTagsProvider.java
type SearchTagsProvider (line 7) | public interface SearchTagsProvider {
type ResultsCallback (line 8) | interface ResultsCallback {
method onResults (line 9) | void onResults(List<Tag> results);
method search (line 11) | void search(String query, ResultsCallback callback);
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/search/vineyard/Option.java
class Option (line 3) | public class Option {
method Option (line 8) | public Option(String title, String value, int iconResource) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/search/vineyard/Tag.java
class Tag (line 10) | public class Tag implements Comparable<Tag>, Parcelable {
method Tag (line 15) | public Tag() {
method compareTo (line 18) | @Override
method describeContents (line 23) | @Override
method writeToParcel (line 28) | @Override
method Tag (line 35) | public Tag(String tag) {
method Tag (line 39) | protected Tag(Parcel in) {
method createFromParcel (line 46) | public Tag createFromParcel(Parcel source) {
method newArray (line 50) | public Tag[] newArray(int size) {
method equals (line 55) | @Override
method hashCode (line 68) | @Override
method from (line 76) | public static List<Tag> from(List<String> tags) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/search/vineyard/User.java
class User (line 6) | public class User implements Parcelable {
method describeContents (line 25) | @Override
method writeToParcel (line 30) | @Override
method User (line 51) | public User() {
method User (line 54) | protected User(Parcel in) {
method createFromParcel (line 75) | public User createFromParcel(Parcel source) {
method newArray (line 79) | public User[] newArray(int size) {
method equals (line 84) | @Override
method hashCode (line 116) | @Override
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/AddDevicePresenter.java
class AddDevicePresenter (line 13) | public class AddDevicePresenter extends BasePresenter<AddDeviceView> {
method AddDevicePresenter (line 20) | private AddDevicePresenter(Context context) {
method instance (line 25) | public static AddDevicePresenter instance(Context context) {
method unhold (line 35) | public void unhold() {
method onViewDestroyed (line 40) | @Override
method onViewInitialized (line 46) | @Override
method onActionClicked (line 52) | public void onActionClicked() {
method updateDeviceCode (line 58) | private void updateDeviceCode() {
method start (line 71) | public void start() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/AppDialogPresenter.java
class AppDialogPresenter (line 18) | public class AppDialogPresenter extends BasePresenter<AppDialogView> {
method AppDialogPresenter (line 40) | public AppDialogPresenter(Context context) {
method instance (line 46) | public static AppDialogPresenter instance(Context context) {
method onFinish (line 59) | @Override
method clear (line 67) | private void clear() {
method backupData (line 76) | private void backupData() {
method resetData (line 85) | private void resetData() {
method onViewInitialized (line 94) | @Override
method onViewDestroyed (line 103) | @Override
method showDialog (line 109) | public void showDialog() {
method showDialog (line 113) | public void showDialog(String dialogTitle) {
method showDialog (line 117) | public void showDialog(Runnable onFinish) {
method showDialog (line 121) | public void showDialog(String dialogTitle, Runnable onFinish) {
method closeDialog (line 137) | public void closeDialog() {
method goBack (line 143) | public void goBack() {
method clearBackstack (line 149) | public void clearBackstack() {
method isDialogShown (line 155) | public boolean isDialogShown() {
method isCommentsDialogShown (line 163) | public boolean isCommentsDialogShown() {
method appendCategory (line 167) | public void appendCategory(OptionCategory category) {
method appendRadioCategory (line 171) | public void appendRadioCategory(String categoryTitle, List<OptionItem>...
method appendCheckedCategory (line 175) | public void appendCheckedCategory(String categoryTitle, List<OptionIte...
method appendStringsCategory (line 179) | public void appendStringsCategory(String categoryTitle, List<OptionIte...
method appendLongTextCategory (line 183) | public void appendLongTextCategory(String categoryTitle, OptionItem it...
method appendChatCategory (line 187) | public void appendChatCategory(String categoryTitle, OptionItem item) {
method appendCommentsCategory (line 191) | public void appendCommentsCategory(String categoryTitle, OptionItem it...
method appendSingleSwitch (line 195) | public void appendSingleSwitch(OptionItem optionItem) {
method appendSingleButton (line 199) | public void appendSingleButton(OptionItem optionItem) {
method showDialogMessage (line 203) | public void showDialogMessage(String dialogTitle, Runnable onClose, in...
method setCloseTimeoutMs (line 213) | public void setCloseTimeoutMs(long timeoutMs) {
method setOnStart (line 217) | public void setOnStart(Runnable onStart) {
method setOnFinish (line 221) | public void setOnFinish(Runnable onFinish) {
method enableTransparent (line 225) | public void enableTransparent(boolean enable) {
method enableOverlay (line 232) | public void enableOverlay(boolean enable) {
method isTransparent (line 236) | public boolean isTransparent() {
method isOverlay (line 240) | public boolean isOverlay() {
method isComments (line 244) | public boolean isComments() {
method enableExpandable (line 257) | public void enableExpandable(boolean enable) {
method setId (line 261) | public void setId(int id) {
method getId (line 265) | public int getId() {
method isEmpty (line 269) | public boolean isEmpty() {
method setupTimeout (line 273) | private void setupTimeout() {
method isTypeComments (line 281) | private boolean isTypeComments() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/BrowsePresenter.java
class BrowsePresenter (line 59) | public class BrowsePresenter extends BasePresenter<BrowseView> implement...
method BrowsePresenter (line 80) | private BrowsePresenter(Context context) {
method instance (line 100) | public static BrowsePresenter instance(Context context) {
method unhold (line 110) | public static void unhold() {
method onViewInitialized (line 114) | @Override
method onViewPaused (line 130) | @Override
method onViewResumed (line 137) | @Override
method refreshIfNeeded (line 144) | private void refreshIfNeeded() {
method saveSelectedItems (line 152) | private void saveSelectedItems() {
method restoreSelectedItems (line 164) | private void restoreSelectedItems() {
method initSectionMappings (line 175) | private void initSectionMappings() {
method initSectionMapping (line 184) | private void initSectionMapping() {
method initRowAndGridMapping (line 214) | private void initRowAndGridMapping() {
method initPinnedSections (line 233) | private void initPinnedSections() {
method initPinnedCallbacks (line 254) | private void initPinnedCallbacks() {
method initSettingsGridMapping (line 264) | private void initSettingsGridMapping() {
method initLocalGridMapping (line 268) | private void initLocalGridMapping() {
method getBlockedChannels (line 273) | private List<Video> getBlockedChannels() {
method updateSections (line 287) | public void updateSections() {
method refreshSections (line 297) | private void refreshSections() {
method initPinnedData (line 338) | private void initPinnedData() {
method sortSections (line 344) | private void sortSections() {
method updateChannelSorting (line 351) | public void updateChannelSorting() {
method updatePlaylistsStyle (line 371) | public void updatePlaylistsStyle() {
method updateCategoryType (line 388) | private void updateCategoryType(int categoryId, int categoryType) {
method onViewDestroyed (line 407) | @Override
method onVideoItemSelected (line 414) | @Override
method onVideoItemClicked (line 431) | @Override
method onVideoItemLongClicked (line 449) | @Override
method onScrollEnd (line 480) | @Override
method onSectionFocused (line 492) | @Override
method onSectionLongPressed (line 501) | @Override
method hasPendingActions (line 506) | @Override
method isItemPinned (line 511) | public boolean isItemPinned(Video item) {
method moveSectionUp (line 517) | public void moveSectionUp(BrowseSection section) {
method moveSectionDown (line 523) | public void moveSectionDown(BrowseSection section) {
method renameSection (line 529) | public void renameSection(BrowseSection section) {
method renameSection (line 535) | public void renameSection(Video section) {
method enableAllSections (line 540) | public void enableAllSections(boolean enable) {
method enableSection (line 553) | public void enableSection(int sectionId, boolean enable) {
method pinItem (line 563) | public void pinItem(Video item) {
method pinItem (line 583) | public void pinItem(String title, int resId, ErrorFragmentData data) {
method appendToSections (line 594) | private void appendToSections(String title, int resId, ErrorFragmentDa...
method unpinItem (line 600) | public void unpinItem(Video item) {
method refresh (line 620) | public void refresh() {
method refresh (line 624) | public void refresh(boolean focusOnContent) {
method updateRefreshTime (line 631) | private void updateRefreshTime() {
method updateCurrentSection (line 635) | private void updateCurrentSection() {
method updateSection (line 646) | private void updateSection(BrowseSection section) {
method updateSettingsGrid (line 678) | private void updateSettingsGrid(BrowseSection section, Callable<List<S...
method updateLocalGrid (line 683) | private void updateLocalGrid(BrowseSection section, Callable<List<Vide...
method updateVideoRows (line 692) | private void updateVideoRows(BrowseSection section, Observable<List<Me...
method updateVideoGrid (line 698) | private void updateVideoGrid(BrowseSection section, Observable<MediaGr...
method updateVideoGrid (line 702) | private void updateVideoGrid(BrowseSection section, Observable<MediaGr...
method updateVideoRows (line 708) | private void updateVideoRows(BrowseSection section, Observable<List<Me...
method updateVideoGrid (line 764) | private void updateVideoGrid(BrowseSection section, Observable<MediaGr...
method continueGroup (line 814) | private void continueGroup(VideoGroup group) {
method continueGroup (line 818) | private void continueGroup(VideoGroup group, boolean showLoading) {
method authCheck (line 880) | private void authCheck(boolean check, Runnable callback) {
method continueGroupIfNeeded (line 906) | private void continueGroupIfNeeded(VideoGroup group) {
method continueGroupIfNeeded (line 913) | private void continueGroupIfNeeded(VideoGroup group, boolean showLoadi...
method disposeActions (line 919) | private void disposeActions() {
method updateChannelUploadsMultiGrid (line 926) | private void updateChannelUploadsMultiGrid(Video item) {
method belongsToChannelUploadsMultiGrid (line 934) | private boolean belongsToChannelUploadsMultiGrid(Video item) {
method belongsToChannelUploads (line 938) | private boolean belongsToChannelUploads(Video item) {
method getCurrentSection (line 942) | @Nullable
method findSectionById (line 947) | private BrowseSection findSectionById(int sectionId) {
method findSectionIndex (line 963) | private int findSectionIndex(int sectionId) {
method findNearestSection (line 991) | private BrowseSection findNearestSection(int sectionId) {
method findNearestSection (line 1001) | private BrowseSection findNearestSection(List<BrowseSection> sections,...
method filterHomeIfNeeded (line 1022) | private void filterHomeIfNeeded(List<MediaGroup> mediaGroups) {
method moveToTopIfNeeded (line 1042) | private int moveToTopIfNeeded(MediaGroup mediaGroup) {
method createPinnedGridAction (line 1050) | private Observable<MediaGroup> createPinnedGridAction(Video item) {
method createPinnedRowAction (line 1058) | private Observable<List<MediaGroup>> createPinnedRowAction(Video item) {
method isMultiGridChannelUploadsSection (line 1065) | public boolean isMultiGridChannelUploadsSection() {
method isSettingsSection (line 1069) | public boolean isSettingsSection() {
method isPlaylistsSection (line 1073) | public boolean isPlaylistsSection() {
method isHomeSection (line 1077) | public boolean isHomeSection() {
method isHistorySection (line 1081) | public boolean isHistorySection() {
method isSubscriptionsSection (line 1085) | public boolean isSubscriptionsSection() {
method isPlaybackQueueSection (line 1089) | public boolean isPlaybackQueueSection() {
method isPinnedSection (line 1093) | public boolean isPinnedSection() {
method isPinnedId (line 1097) | private boolean isPinnedId(int id) {
method isSection (line 1101) | private boolean isSection(int sectionId) {
method selectSection (line 1105) | public void selectSection(int sectionId) {
method inForeground (line 1126) | public boolean inForeground() {
method isGridSection (line 1130) | private boolean isGridSection() {
method onAccountChanged (line 1134) | @Override
method getCurrentVideo (line 1148) | public Video getCurrentVideo() {
method initPasswordSection (line 1152) | private void initPasswordSection() {
method createPinnedMapping (line 1162) | private void createPinnedMapping(Video item) {
method createPinnedSection (line 1170) | private BrowseSection createPinnedSection(Video item) {
method enableRows (line 1175) | private boolean enableRows(Video item) {
method handleLoadError (line 1179) | private void handleLoadError(Throwable error) {
method appendLocalHistory (line 1212) | private void appendLocalHistory(VideoGroup videoGroup) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/ChannelPresenter.java
class ChannelPresenter (line 29) | public class ChannelPresenter extends BasePresenter<ChannelView> impleme...
type OnChannelId (line 41) | private interface OnChannelId {
method onChannelId (line 42) | void onChannelId(String channelId);
type OnUploadsRow (line 45) | public interface OnUploadsRow {
method onUploadsRow (line 46) | void onUploadsRow(Observable<MediaGroup> row);
method ChannelPresenter (line 49) | public ChannelPresenter(Context context) {
method instance (line 54) | public static ChannelPresenter instance(Context context) {
method onViewInitialized (line 64) | @Override
method onViewDestroyed (line 80) | @Override
method onFinish (line 86) | @Override
method onVideoItemSelected (line 97) | @Override
method onVideoItemClicked (line 102) | @Override
method onVideoItemLongClicked (line 107) | @Override
method onScrollEnd (line 112) | @Override
method hasPendingActions (line 131) | @Override
method canOpenChannel (line 136) | public static boolean canOpenChannel(Video item) {
method openChannel (line 144) | public void openChannel(Video item) {
method openChannel (line 149) | public void openChannel(String channelId) {
method getChannelId (line 168) | public String getChannelId() {
method setChannelId (line 172) | public void setChannelId(String channelId) {
method getChannel (line 176) | public Video getChannel() {
method setChannel (line 180) | public void setChannel(Video channel) {
method disposeActions (line 184) | private void disposeActions() {
method updateRows (line 191) | private void updateRows(Observable<List<MediaGroup>> group) {
method obtainChannelObservable (line 208) | public Observable<List<MediaGroup>> obtainChannelObservable(String cha...
method updateRows (line 212) | public void updateRows(List<MediaGroup> mediaGroups) {
method continueGroup (line 237) | private void continueGroup(VideoGroup group) {
method moveToTopIfNeeded (line 280) | private void moveToTopIfNeeded(List<MediaGroup> mediaGroups) {
method moveToTop (line 287) | private void moveToTop(List<MediaGroup> mediaGroups, int rowNameResId) {
method clear (line 301) | public void clear() {
method extractChannelId (line 309) | private void extractChannelId(Video item, OnChannelId callback) {
method onSearchSettingsClicked (line 356) | public void onSearchSettingsClicked() {
method onSearchSubmit (line 391) | public boolean onSearchSubmit(String query) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/ChannelUploadsPresenter.java
class ChannelUploadsPresenter (line 35) | public class ChannelUploadsPresenter extends BasePresenter<ChannelUpload...
method ChannelUploadsPresenter (line 46) | public ChannelUploadsPresenter(Context context) {
method instance (line 51) | public static ChannelUploadsPresenter instance(Context context) {
method onViewInitialized (line 61) | @Override
method onViewDestroyed (line 68) | @Override
method onFinish (line 74) | @Override
method onVideoItemSelected (line 86) | @Override
method onVideoItemClicked (line 91) | @Override
method onVideoItemLongClicked (line 96) | @Override
method onScrollEnd (line 107) | @Override
method hasPendingActions (line 130) | @Override
method openChannel (line 135) | public void openChannel(Video item) {
method obtainGroup (line 152) | public void obtainGroup(Video item, OnMediaGroup callback) {
method obtainGroup (line 156) | public void obtainGroup(Video item, OnMediaGroup callback, OnError onE...
method obtainUploadsObservable (line 162) | public Observable<MediaGroup> obtainUploadsObservable(Video item) {
method getChannel (line 181) | public Video getChannel() {
method setChannel (line 185) | public void setChannel(Video channel) {
method disposeActions (line 189) | private void disposeActions() {
method continueGroup (line 195) | private void continueGroup(VideoGroup group) {
method update (line 235) | private void update(Video item) {
method update (line 244) | private void update(Observable<MediaGroup> group) {
method update (line 262) | public void update(MediaGroup mediaGroup) {
method update (line 278) | private void update(VideoGroup group) {
method obtainGroup (line 294) | private void obtainGroup(MediaItem mediaItem, OnMediaGroup callback, O...
method findPlaylistRow (line 320) | private MediaGroup findPlaylistRow(MediaItemMetadata mediaItemMetadata) {
method clear (line 335) | public void clear() {
method refresh (line 345) | public void refresh() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/DetailsPresenter.java
class DetailsPresenter (line 10) | public class DetailsPresenter extends BasePresenter<DetailsView> {
method DetailsPresenter (line 15) | private DetailsPresenter(Context context) {
method instance (line 19) | public static DetailsPresenter instance(Context context) {
method onViewInitialized (line 29) | @Override
method openVideo (line 34) | public void openVideo(Video item) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/GoogleSignInPresenter.java
class GoogleSignInPresenter (line 12) | public class GoogleSignInPresenter extends SignInPresenter {
method GoogleSignInPresenter (line 20) | private GoogleSignInPresenter(Context context) {
method instance (line 25) | public static GoogleSignInPresenter instance(Context context) {
method unhold (line 35) | public void unhold() {
method onViewDestroyed (line 40) | @Override
method onViewInitialized (line 46) | @Override
method onActionClicked (line 53) | @Override
method updateUserCode (line 60) | private void updateUserCode() {
method start (line 83) | @Override
method start (line 89) | public void start(Runnable onSuccess) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/PlaybackPresenter.java
class PlaybackPresenter (line 36) | public class PlaybackPresenter extends BasePresenter<PlaybackView> imple...
method add (line 41) | @Override
method PlaybackPresenter (line 53) | private PlaybackPresenter(Context context) {
method instance (line 69) | public static PlaybackPresenter instance(Context context) {
method onViewInitialized (line 79) | @Override
method initControllers (line 86) | private void initControllers() {
method openVideo (line 91) | public void openVideo(String videoId) {
method openVideo (line 98) | public void openVideo(String videoId, boolean finishOnEnded, long time...
method openVideo (line 110) | public void openVideo(Video video) {
method getVideo (line 129) | public Video getVideo() {
method isRunningInBackground (line 133) | public boolean isRunningInBackground() {
method isInPipMode (line 142) | public boolean isInPipMode() {
method isOverlayShown (line 146) | public boolean isOverlayShown() {
method isPlaying (line 150) | public boolean isPlaying() {
method isEngineBlocked (line 154) | public boolean isEngineBlocked() {
method isEngineInitialized (line 158) | public boolean isEngineInitialized() {
method forceFinish (line 166) | public void forceFinish() {
method setPosition (line 172) | public void setPosition(String timeCode) {
method setPosition (line 176) | public void setPosition(long positionMs) {
method setView (line 194) | @Override
method getPlayer (line 207) | public PlaybackView getPlayer() {
method getActivity (line 211) | public Activity getActivity() {
method getController (line 215) | @SuppressWarnings("unchecked")
method onNewVideo (line 228) | @Override
method onFinish (line 235) | @Override
method onInit (line 240) | @Override
method onMetadata (line 245) | @Override
method chainProcess (line 254) | private boolean chainProcess(ChainProcessor<PlayerEventListener> proce...
method process (line 258) | private void process(Processor<PlayerEventListener> processor) {
method onViewCreated (line 266) | @Override
method onViewDestroyed (line 271) | @Override
method onViewPaused (line 276) | @Override
method onViewResumed (line 283) | @Override
method onSourceChanged (line 294) | @Override
method onEngineInitialized (line 299) | @Override
method onEngineReleased (line 306) | @Override
method onEngineError (line 313) | @Override
method onPlay (line 318) | @Override
method onPause (line 323) | @Override
method onPlayClicked (line 328) | @Override
method onPauseClicked (line 333) | @Override
method onSeekEnd (line 338) | @Override
method onSeekPositionChanged (line 343) | @Override
method onSpeedChanged (line 348) | @Override
method onPlayEnd (line 353) | @Override
method onBuffering (line 358) | @Override
method onKeyDown (line 363) | @Override
method onVideoLoaded (line 368) | @Override
method onTickle (line 373) | @Override
method onSuggestionItemClicked (line 382) | @Override
method onSuggestionItemLongClicked (line 387) | @Override
method onScrollEnd (line 392) | @Override
method onPreviousClicked (line 397) | @Override
method onNextClicked (line 402) | @Override
method onTrackSelected (line 407) | @Override
method onControlsShown (line 412) | @Override
method onTrackChanged (line 417) | @Override
method onButtonClicked (line 422) | @Override
method onButtonLongClicked (line 427) | @Override
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/SearchPresenter.java
class SearchPresenter (line 31) | public class SearchPresenter extends BasePresenter<SearchView> implement...
method SearchPresenter (line 48) | private SearchPresenter(Context context) {
method instance (line 53) | public static SearchPresenter instance(Context context) {
method onViewInitialized (line 63) | @Override
method onViewDestroyed (line 75) | @Override
method onFinish (line 81) | @Override
method onVideoItemSelected (line 94) | @Override
method onVideoItemClicked (line 99) | @Override
method onVideoItemLongClicked (line 108) | @Override
method onTagLongClicked (line 117) | public void onTagLongClicked(Tag item) {
method hasPendingActions (line 131) | @Override
method onSearch (line 136) | public void onSearch(String searchText) {
method loadSearchResult (line 149) | private void loadSearchResult(String searchText) {
method continueGroup (line 185) | private void continueGroup(VideoGroup group) {
method onScrollEnd (line 223) | @Override
method startVoice (line 242) | public void startVoice() {
method startSearch (line 246) | public void startSearch(String searchText) {
method startPlay (line 250) | public void startPlay(String searchText) {
method getCurrentVideo (line 254) | public Video getCurrentVideo() {
method startSearch (line 258) | private void startSearch(String searchText, boolean isVoice, boolean s...
method startSearchInt (line 267) | private void startSearchInt() {
method onSearchSettingsClicked (line 279) | public void onSearchSettingsClicked() {
method disposeActions (line 287) | public void disposeActions() {
method showSettingsDialog (line 298) | private void showSettingsDialog() {
method appendFilterByDateCategory (line 310) | private void appendFilterByDateCategory(AppDialogPresenter settingsPre...
method appendFilterByDurationCategory (line 331) | private void appendFilterByDurationCategory(AppDialogPresenter setting...
method appendFilterByTypeCategory (line 350) | private void appendFilterByTypeCategory(AppDialogPresenter settingsPre...
method appendFilterByFeatureCategory (line 370) | private void appendFilterByFeatureCategory(AppDialogPresenter settings...
method appendSortByCategory (line 388) | private void appendSortByCategory(AppDialogPresenter settingsPresenter) {
method forceFinish (line 407) | public void forceFinish() {
method startPlayFirstVideo (line 413) | private void startPlayFirstVideo(VideoGroup group) {
method loadSearchResult (line 428) | private void loadSearchResult() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/SignInPresenter.java
class SignInPresenter (line 9) | public class SignInPresenter extends BasePresenter<SignInView> {
method SignInPresenter (line 16) | protected SignInPresenter(Context context) {
method instance (line 20) | public static SignInPresenter instance(Context context) {
method unhold (line 30) | public void unhold() {
method onViewDestroyed (line 34) | @Override
method onViewInitialized (line 40) | @Override
method onActionClicked (line 62) | public void onActionClicked() {
method doWait (line 68) | private void doWait(boolean doWait) {
method isWaiting (line 72) | protected final boolean isWaiting() {
method start (line 76) | public void start() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/SplashPresenter.java
class SplashPresenter (line 38) | public class SplashPresenter extends BasePresenter<SplashView> {
type IntentProcessor (line 50) | private interface IntentProcessor {
method process (line 51) | boolean process(Intent intent);
method SplashPresenter (line 54) | private SplashPresenter(Context context) {
method instance (line 58) | public static SplashPresenter instance(Context context) {
method unhold (line 68) | public static void unhold() {
method onViewInitialized (line 75) | @Override
method runOneTimeTasks (line 88) | private void runOneTimeTasks() {
method runPerInstanceTasks (line 99) | private void runPerInstanceTasks() {
method runPerViewTasks (line 107) | private void runPerViewTasks() {
method runBackgroundTasks (line 117) | private void runBackgroundTasks() {
method showAccountSelectionIfNeeded (line 125) | private void showAccountSelectionIfNeeded() {
method checkAccountPassword (line 129) | private void checkAccountPassword() {
method checkForUpdates (line 139) | private void checkForUpdates() {
method initVideoStateService (line 144) | private void initVideoStateService() {
method initStreamReminderService (line 150) | private void initStreamReminderService() {
method initGlobalPrefs (line 161) | private void initGlobalPrefs() {
method initProxy (line 171) | private void initProxy() {
method enableHistoryIfNeeded (line 180) | private void enableHistoryIfNeeded() {
method getBridgePackageName (line 188) | public String getBridgePackageName() {
method initIntentChain (line 192) | private void initIntentChain() {
method applyNewIntent (line 316) | public void applyNewIntent(Intent intent) {
method checkMasterPassword (line 332) | private void checkMasterPassword(Runnable onSuccess) {
method enablePlayerOnlyModeIfNeeded (line 357) | private void enablePlayerOnlyModeIfNeeded(Intent intent) {
method updateBadgeIcon (line 367) | private void updateBadgeIcon() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/WebBrowserPresenter.java
class WebBrowserPresenter (line 8) | public class WebBrowserPresenter extends BasePresenter<WebBrowserView> {
method WebBrowserPresenter (line 13) | private WebBrowserPresenter(Context context) {
method instance (line 17) | public static WebBrowserPresenter instance(Context context) {
method unhold (line 27) | public static void unhold() {
method onViewInitialized (line 31) | @Override
method loadUrl (line 38) | public void loadUrl(String url) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/YTSignInPresenter.java
class YTSignInPresenter (line 14) | public class YTSignInPresenter extends SignInPresenter {
method YTSignInPresenter (line 24) | private YTSignInPresenter(Context context) {
method instance (line 29) | public static YTSignInPresenter instance(Context context) {
method unhold (line 39) | public void unhold() {
method onViewDestroyed (line 44) | @Override
method onViewInitialized (line 50) | @Override
method onActionClicked (line 57) | @Override
method updateUserCode (line 64) | private void updateUserCode() {
method start (line 85) | public void start() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/base/BasePresenter.java
class BasePresenter (line 38) | public abstract class BasePresenter<T> implements Presenter<T> {
method BasePresenter (line 43) | public BasePresenter(Context context) {
method setView (line 47) | @Override
method getView (line 54) | @Override
method setContext (line 61) | @Override
method getContext (line 76) | @Override
method onViewInitialized (line 96) | @Override
method onViewDestroyed (line 101) | @Override
method onViewPaused (line 109) | @Override
method onViewResumed (line 114) | @Override
method onFinish (line 126) | @Override
method removeItem (line 134) | protected void removeItem(Video item) {
method removeItemAuthor (line 138) | protected void removeItemAuthor(Video item) {
method removeItem (line 142) | private void removeItem(List<Video> items, int action) {
method syncItem (line 154) | public boolean syncItem(Video item) {
method syncItem (line 158) | public boolean syncItem(List<Video> items) {
method canViewBeSynced (line 170) | private boolean canViewBeSynced() {
method updateView (line 178) | private boolean updateView(VideoGroup group, T view) {
method enableSync (line 196) | private void enableSync() {
method checkView (line 205) | private static <T> boolean checkView(T view) {
method getViewActivity (line 211) | @SuppressWarnings("deprecation")
method getMainUIData (line 230) | protected MainUIData getMainUIData() {
method getGeneralData (line 234) | protected GeneralData getGeneralData() {
method getSearchData (line 238) | protected SearchData getSearchData() {
method getSidebarService (line 242) | protected SidebarService getSidebarService() {
method getCommentsService (line 246) | protected CommentsService getCommentsService() {
method getContentService (line 250) | protected ContentService getContentService() {
method getSignInService (line 254) | protected SignInService getSignInService() {
method getNotificationsService (line 258) | protected NotificationsService getNotificationsService() {
method getMediaItemService (line 262) | protected MediaItemService getMediaItemService() {
method getServiceManager (line 266) | protected MediaServiceManager getServiceManager() {
method getViewManager (line 270) | protected ViewManager getViewManager() {
method getTickleManager (line 274) | protected TickleManager getTickleManager() {
method getPlaybackPresenter (line 278) | protected PlaybackPresenter getPlaybackPresenter() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/ATVBridgePresenter.java
class ATVBridgePresenter (line 6) | public class ATVBridgePresenter extends BridgePresenter {
method ATVBridgePresenter (line 12) | public ATVBridgePresenter(Context context) {
method instance (line 16) | public static ATVBridgePresenter instance(Context context) {
method unhold (line 26) | public void unhold() {
method getPackageName (line 30) | @Override
method getPackageUrl (line 35) | @Override
method getPackageSignatureHash (line 40) | @Override
method checkLauncher (line 45) | @Override
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/AccountSelectionPresenter.java
class AccountSelectionPresenter (line 24) | public class AccountSelectionPresenter extends BasePresenter<Void> {
method AccountSelectionPresenter (line 30) | public AccountSelectionPresenter(Context context) {
method instance (line 36) | public static AccountSelectionPresenter instance(Context context) {
method show (line 46) | public void show() {
method show (line 50) | public void show(boolean force) {
method nextAccountOrDialog (line 59) | public void nextAccountOrDialog() {
method unhold (line 63) | public void unhold() {
method createAndShowDialog (line 67) | private void createAndShowDialog(List<Account> accounts, boolean force) {
method appendAccountSelection (line 79) | private void appendAccountSelection(List<Account> accounts, AppDialogP...
method nextAccountOrDialog (line 101) | private void nextAccountOrDialog(List<Account> accounts) {
method selectAccount (line 124) | public void selectAccount(Account account) {
method formatAccount (line 135) | private String formatAccount(Account account) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/AmazonBridgePresenter.java
class AmazonBridgePresenter (line 6) | public class AmazonBridgePresenter extends BridgePresenter {
method AmazonBridgePresenter (line 12) | public AmazonBridgePresenter(Context context) {
method instance (line 16) | public static AmazonBridgePresenter instance(Context context) {
method unhold (line 26) | public void unhold() {
method getPackageName (line 30) | @Override
method getPackageUrl (line 35) | @Override
method getPackageSignatureHash (line 40) | @Override
method checkLauncher (line 45) | @Override
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/AppUpdatePresenter.java
class AppUpdatePresenter (line 22) | public class AppUpdatePresenter extends BasePresenter<Void> implements A...
method AppUpdatePresenter (line 30) | public AppUpdatePresenter(Context context) {
method instance (line 37) | public static AppUpdatePresenter instance(Context context) {
method unhold (line 47) | public static void unhold() {
method start (line 51) | public void start(boolean forceCheck) {
method onUpdateFound (line 62) | @Override
method onUpdateError (line 74) | @Override
method showUpdateDialog (line 90) | private void showUpdateDialog(String versionName, List<String> changel...
method pinUpdateSection (line 110) | private void pinUpdateSection(String versionName, List<String> changel...
method createChangelogOptions (line 137) | private List<OptionItem> createChangelogOptions(List<String> changelog) {
method createChangelog (line 147) | private String createChangelog(List<String> changelog) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/BootDialogPresenter.java
class BootDialogPresenter (line 10) | public class BootDialogPresenter extends BasePresenter<Void> {
method BootDialogPresenter (line 14) | public BootDialogPresenter(Context context) {
method instance (line 18) | public static BootDialogPresenter instance(Context context) {
method start (line 32) | public void start() {
method startUpdatePresenter (line 36) | private void startUpdatePresenter() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/BridgePresenter.java
class BridgePresenter (line 24) | abstract class BridgePresenter extends BasePresenter<Void> implements Mo...
method onDownloadCompleted (line 31) | @Override
method BridgePresenter (line 45) | public BridgePresenter(Context context) {
method start (line 51) | public void start() {
method startDialog (line 60) | private void startDialog() {
method runBridgeInstaller (line 78) | public void runBridgeInstaller(boolean force) {
method isOldApkInstalled (line 96) | private boolean isOldApkInstalled() {
method getPackageSignature (line 102) | private PackageInfo getPackageSignature(String pkgName) {
method downloadPackageFromUrl (line 115) | private void downloadPackageFromUrl(Context context, String pkgUrl) {
method installBridgeFromPath (line 122) | private void installBridgeFromPath(Context context) {
method onResult (line 126) | @Override
method installBridgeIfNeeded (line 135) | private void installBridgeIfNeeded() {
method getPackageName (line 149) | protected abstract String getPackageName();
method getPackageUrl (line 150) | protected abstract String getPackageUrl();
method getPackageSignatureHash (line 151) | protected abstract Integer[] getPackageSignatureHash();
method checkLauncher (line 152) | protected abstract boolean checkLauncher();
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/QuickRestorePresenter.java
class QuickRestorePresenter (line 12) | public class QuickRestorePresenter extends BasePresenter<Void> {
method QuickRestorePresenter (line 15) | public QuickRestorePresenter(Context context) {
method instance (line 19) | public static QuickRestorePresenter instance(Context context) {
method unhold (line 29) | public void unhold() {
method start (line 33) | public void start() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/StableRestorePresenter.java
class StableRestorePresenter (line 8) | public class StableRestorePresenter extends BridgePresenter {
method StableRestorePresenter (line 17) | public StableRestorePresenter(Context context) {
method instance (line 21) | public static StableRestorePresenter instance(Context context) {
method unhold (line 31) | public void unhold() {
method getPackageName (line 35) | @Override
method getPackageUrl (line 40) | @Override
method getPackageSignatureHash (line 55) | @Override
method checkLauncher (line 60) | @Override
method isSupported (line 65) | public boolean isSupported() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/VideoActionPresenter.java
class VideoActionPresenter (line 14) | public class VideoActionPresenter extends BasePresenter<Void> {
method VideoActionPresenter (line 17) | private VideoActionPresenter(Context context) {
method instance (line 21) | public static VideoActionPresenter instance(Context context) {
method apply (line 25) | public void apply(Video item) {
method startFistPlaylistItem (line 50) | private void startFistPlaylistItem(Video item) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/menu/BaseMenuPresenter.java
class BaseMenuPresenter (line 31) | public abstract class BaseMenuPresenter extends BasePresenter<Void> {
method BaseMenuPresenter (line 44) | protected BaseMenuPresenter(Context context) {
method getVideo (line 50) | protected abstract Video getVideo();
method getSection (line 51) | protected BrowseSection getSection() { return null; }
method getDialogPresenter (line 52) | protected abstract AppDialogPresenter getDialogPresenter();
method getCallback (line 53) | protected abstract VideoMenuCallback getCallback();
method closeDialog (line 55) | public void closeDialog() {
method appendTogglePinVideoToSidebarButton (line 62) | protected void appendTogglePinVideoToSidebarButton() {
method togglePinToSidebar (line 97) | private void togglePinToSidebar(Video section) {
method createPinnedPlaylist (line 113) | private static Video createPinnedPlaylist(Video video) {
method createPinnedChannel (line 125) | private static Video createPinnedChannel(Video video) {
method appendUnpinVideoFromSidebarButton (line 137) | protected void appendUnpinVideoFromSidebarButton() {
method appendUnpinSectionFromSidebarButton (line 156) | protected void appendUnpinSectionFromSidebarButton() {
method appendAccountSelectionButton (line 175) | protected void appendAccountSelectionButton() {
method appendSaveRemovePlaylistButton (line 187) | protected void appendSaveRemovePlaylistButton() {
method syncToggleSaveRemovePlaylist (line 241) | private void syncToggleSaveRemovePlaylist(Video original, String playl...
method toggleSaveRemovePlaylist (line 256) | private void toggleSaveRemovePlaylist(Video video) {
method removePlaylist (line 285) | private void removePlaylist(Video video) {
method savePlaylist (line 300) | private void savePlaylist(Video video) {
method getFirstPlaylistId (line 309) | private String getFirstPlaylistId(MediaGroup mediaGroup) {
method appendCreatePlaylistButton (line 318) | protected void appendCreatePlaylistButton() {
method appendAddToNewPlaylistButton (line 338) | protected void appendAddToNewPlaylistButton() {
method showCreatePlaylistDialog (line 356) | private void showCreatePlaylistDialog(Video video) {
method appendRenamePlaylistButton (line 383) | protected void appendRenamePlaylistButton() {
method showRenamePlaylistDialog (line 403) | private void showRenamePlaylistDialog(Video video) {
method showRenamePlaylistDialogUploads (line 411) | private void showRenamePlaylistDialogUploads(Video video) {
method showRenamePlaylistDialogSimple (line 428) | private void showRenamePlaylistDialogSimple(Video video) {
method appendToggleHistoryButton (line 455) | protected void appendToggleHistoryButton() {
method appendClearHistoryButton (line 482) | protected void appendClearHistoryButton() {
method appendUpdateCheckButton (line 504) | protected void appendUpdateCheckButton() {
method appendToggleExcludeFromContentBlockButton (line 514) | protected void appendToggleExcludeFromContentBlockButton() {
method updateEnabledMenuItems (line 528) | protected void updateEnabledMenuItems() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/menu/ChannelUploadsMenuPresenter.java
class ChannelUploadsMenuPresenter (line 23) | public class ChannelUploadsMenuPresenter extends BaseMenuPresenter {
method ChannelUploadsMenuPresenter (line 31) | private ChannelUploadsMenuPresenter(Context context) {
method instance (line 39) | public static ChannelUploadsMenuPresenter instance(Context context) {
method getVideo (line 43) | @Override
method getDialogPresenter (line 48) | @Override
method getCallback (line 53) | @Override
method showMenu (line 58) | public void showMenu(Video video, VideoMenuCallback callback) {
method showMenu (line 63) | public void showMenu(Video video) {
method prepareAndShowDialog (line 75) | private void prepareAndShowDialog() {
method appendOpenChannelUploadsButton (line 86) | private void appendOpenChannelUploadsButton() {
method appendOpenChannelButton (line 95) | private void appendOpenChannelButton() {
method appendUnsubscribeButton (line 104) | private void appendUnsubscribeButton() {
method appendMarkAsWatched (line 142) | private void appendMarkAsWatched() {
method unsubscribe (line 160) | private void unsubscribe(String channelId) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/menu/SectionMenuPresenter.java
class SectionMenuPresenter (line 30) | public class SectionMenuPresenter extends BaseMenuPresenter {
method SectionMenuPresenter (line 42) | private SectionMenuPresenter(Context context) {
method instance (line 49) | public static SectionMenuPresenter instance(Context context) {
method getVideo (line 53) | @Override
method getSection (line 58) | @Override
method getDialogPresenter (line 63) | @Override
method getCallback (line 68) | @Override
method showMenu (line 73) | public void showMenu(BrowseSection section) {
method obtainPlaylistsAndShowDialogSigned (line 86) | private void obtainPlaylistsAndShowDialogSigned() {
method prepareAndShowDialogSigned (line 90) | private void prepareAndShowDialogSigned() {
method prepareAndShowDialogUnsigned (line 121) | private void prepareAndShowDialogUnsigned() {
method appendRefreshButton (line 148) | private void appendRefreshButton() {
method appendMoveSectionButton (line 167) | private void appendMoveSectionButton() {
method appendRenameSectionButton (line 189) | private void appendRenameSectionButton() {
method appendReturnToBackgroundVideoButton (line 214) | private void appendReturnToBackgroundVideoButton() {
method appendMarkAllChannelsWatchedButton (line 227) | private void appendMarkAllChannelsWatchedButton() {
method processNextChannel (line 252) | private void processNextChannel(MediaServiceManager serviceManager, It...
method disposeActions (line 268) | private void disposeActions() {
method updateEnabledMenuItems (line 272) | @Override
method initMenuMapping (line 289) | private void initMenuMapping() {
method appendContextMenuItem (line 300) | private void appendContextMenuItem(ContextMenuProvider provider) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/menu/VideoMenuPresenter.java
class VideoMenuPresenter (line 43) | public class VideoMenuPresenter extends BaseMenuPresenter {
type VideoMenuCallback (line 84) | public interface VideoMenuCallback {
method onItemAction (line 93) | void onItemAction(Video videoItem, int action);
class MenuAction (line 96) | public static class MenuAction {
method MenuAction (line 100) | public MenuAction(Runnable action, boolean isAuth) {
method run (line 105) | public void run() {
method isAuth (line 109) | public boolean isAuth() {
method VideoMenuPresenter (line 114) | private VideoMenuPresenter(Context context) {
method instance (line 124) | public static VideoMenuPresenter instance(Context context) {
method getVideo (line 128) | @Override
method getDialogPresenter (line 133) | @Override
method getCallback (line 138) | @Override
method showMenu (line 143) | public void showMenu(Video video, VideoMenuCallback callback) {
method showMenu (line 148) | public void showMenu(Video video) {
method bootstrapPrepareAndShowDialogSigned (line 159) | private void bootstrapPrepareAndShowDialogSigned() {
method prepareAndShowDialogSigned (line 176) | private void prepareAndShowDialogSigned() {
method prepareAndShowDialogUnsigned (line 197) | private void prepareAndShowDialogUnsigned() {
method appendAddToPlaylistButton (line 217) | private void appendAddToPlaylistButton() {
method appendAddToRecentPlaylistButton (line 233) | private void appendAddToRecentPlaylistButton() {
method isAddToRecentPlaylistButtonEnabled (line 248) | private boolean isAddToRecentPlaylistButtonEnabled() {
method appendSimpleAddToRecentPlaylistButton (line 252) | private void appendSimpleAddToRecentPlaylistButton(String playlistId, ...
method appendOpenChannelButton (line 298) | private void appendOpenChannelButton() {
method appendOpenPlaylistButton (line 316) | private void appendOpenPlaylistButton() {
method appendOpenChannelUploadsButton (line 335) | private void appendOpenChannelUploadsButton() {
method appendNotInterestedButton (line 344) | private void appendNotInterestedButton() {
method appendNotRecommendChannelButton (line 373) | private void appendNotRecommendChannelButton() {
method appendBlockChannelButton (line 402) | private void appendBlockChannelButton() {
method appendRemoveFromHistoryButton (line 450) | private void appendRemoveFromHistoryButton() {
method onRemoveFromHistoryDone (line 473) | private void onRemoveFromHistoryDone() {
method appendRemoveFromSubscriptionsButton (line 483) | private void appendRemoveFromSubscriptionsButton() {
method appendRemoveFromNotificationsButton (line 510) | private void appendRemoveFromNotificationsButton() {
method appendMarkAsWatchedButton (line 529) | private void appendMarkAsWatchedButton() {
method appendShareLinkButton (line 544) | private void appendShareLinkButton() {
method appendShareQRLinkButton (line 552) | private void appendShareQRLinkButton() {
method appendShareEmbedLinkButton (line 560) | private void appendShareEmbedLinkButton() {
method appendOpenDescriptionButton (line 568) | private void appendOpenDescriptionButton() {
method appendOpenCommentsButton (line 600) | private void appendOpenCommentsButton() {
method appendPlayVideoButton (line 621) | private void appendPlayVideoButton() {
method appendPlayVideoIncognitoButton (line 635) | private void appendPlayVideoIncognitoButton() {
method appendPlayFromStartButton (line 650) | private void appendPlayFromStartButton() {
method showLongTextDialog (line 666) | private void showLongTextDialog(String description) {
method appendSubscribeButton (line 671) | private void appendSubscribeButton() {
method appendReturnToBackgroundVideoButton (line 689) | private void appendReturnToBackgroundVideoButton() {
method appendAddToPlaybackQueueButton (line 702) | private void appendAddToPlaybackQueueButton() {
method appendRemoveFromPlaybackQueueButton (line 737) | private void appendRemoveFromPlaybackQueueButton() {
method appendPlayNextButton (line 770) | private void appendPlayNextButton() {
method appendShowPlaybackQueueButton (line 803) | private void appendShowPlaybackQueueButton() {
method appendPlaylistOrderButton (line 820) | private void appendPlaylistOrderButton() {
method appendStreamReminderButton (line 838) | private void appendStreamReminderButton() {
method addRemoveFromPlaylist (line 860) | private void addRemoveFromPlaylist(String playlistId, String playlistT...
method toggleSubscribe (line 905) | private void toggleSubscribe() {
method toggleSubscribe (line 927) | private void toggleSubscribe(Video video) {
method updateEnabledMenuItems (line 948) | @Override
method initMenuMapping (line 982) | private void initMenuMapping() {
method appendContextMenuItem (line 1027) | private void appendContextMenuItem(ContextMenuProvider provider) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/menu/providers/ContextMenuManager.java
class ContextMenuManager (line 13) | public class ContextMenuManager {
method ContextMenuManager (line 16) | public ContextMenuManager(Context context) {
method getProviders (line 24) | public List<ContextMenuProvider> getProviders() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/menu/providers/ContextMenuProvider.java
class ContextMenuProvider (line 10) | public abstract class ContextMenuProvider {
method ContextMenuProvider (line 18) | public ContextMenuProvider(Context context, int idx) {
method getTitleResId (line 24) | public abstract int getTitleResId();
method onClicked (line 25) | public abstract void onClicked(Video item, VideoMenuCallback callback);
method isEnabled (line 26) | public abstract boolean isEnabled(Video item);
method getMenuType (line 27) | public abstract int getMenuType();
method getContext (line 29) | public final Context getContext() {
method getId (line 33) | public final long getId() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/menu/providers/channelgroup/ChannelGroupMenuProvider.java
class ChannelGroupMenuProvider (line 27) | public class ChannelGroupMenuProvider extends ContextMenuProvider {
method ChannelGroupMenuProvider (line 30) | public ChannelGroupMenuProvider(@NonNull Context context, int idx) {
method getTitleResId (line 35) | @Override
method onClicked (line 40) | @Override
method isEnabled (line 45) | @Override
method getMenuType (line 50) | @Override
method showGroupDialogAndFetchChannel (line 55) | private void showGroupDialogAndFetchChannel(Video item, VideoMenuCallb...
method showGroupDialog (line 68) | private void showGroupDialog(Video item, VideoMenuCallback callback) {
method pinGroups (line 136) | private void pinGroups(@NonNull List<ItemGroup> newGroups) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/menu/providers/channelgroup/ChannelGroupServiceWrapper.java
class ChannelGroupServiceWrapper (line 19) | public class ChannelGroupServiceWrapper implements ProfileChangeListener {
method ChannelGroupServiceWrapper (line 25) | private ChannelGroupServiceWrapper(Context context) {
method instance (line 31) | public static ChannelGroupServiceWrapper instance(Context context) {
method getChannelGroups (line 39) | public List<ItemGroup> getChannelGroups() {
method addChannelGroup (line 43) | public void addChannelGroup(ItemGroup group) {
method removeChannelGroup (line 47) | public void removeChannelGroup(ItemGroup group) {
method findChannelIdsForGroup (line 51) | public String[] findChannelIdsForGroup(String channelGroupId) {
method findChannelGroupById (line 55) | public ItemGroup findChannelGroupById(String channelGroupId) {
method findChannelGroupByTitle (line 59) | public ItemGroup findChannelGroupByTitle(String title) {
method createChannelGroup (line 63) | public ItemGroup createChannelGroup(String title, String iconUrl, List...
method createChannel (line 67) | public Item createChannel(String title, String iconUrl, String channel...
method renameChannelGroup (line 71) | public void renameChannelGroup(ItemGroup channelGroup, String title) {
method importGroupsObserve (line 75) | public Observable<List<ItemGroup>> importGroupsObserve(Uri uri) {
method importGroupsObserve (line 79) | public Observable<List<ItemGroup>> importGroupsObserve(File file) {
method isEmpty (line 83) | public boolean isEmpty() {
method restoreState (line 87) | private void restoreState() {
method onProfileChanged (line 95) | @Override
method getService (line 100) | private ChannelGroupService getService() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/menu/providers/channelgroup/RemoveGroupMenuProvider.java
class RemoveGroupMenuProvider (line 15) | public class RemoveGroupMenuProvider extends ContextMenuProvider {
method RemoveGroupMenuProvider (line 18) | public RemoveGroupMenuProvider(@NonNull Context context, int idx) {
method getTitleResId (line 23) | @Override
method onClicked (line 28) | @Override
method isEnabled (line 39) | @Override
method getMenuType (line 44) | @Override
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/menu/providers/channelgroup/RenameGroupMenuProvider.java
class RenameGroupMenuProvider (line 16) | public class RenameGroupMenuProvider extends ContextMenuProvider {
method RenameGroupMenuProvider (line 19) | public RenameGroupMenuProvider(@NonNull Context context, int idx) {
method getTitleResId (line 24) | @Override
method onClicked (line 29) | @Override
method isEnabled (line 52) | @Override
method getMenuType (line 57) | @Override
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/interfaces/Presenter.java
type Presenter (line 5) | public interface Presenter<T> {
method setView (line 6) | void setView(T view);
method getView (line 7) | T getView();
method setContext (line 8) | void setContext(Context context);
method getContext (line 9) | Context getContext();
method onViewInitialized (line 10) | void onViewInitialized();
method onViewDestroyed (line 11) | void onViewDestroyed();
method onViewPaused (line 12) | void onViewPaused();
method onViewResumed (line 13) | void onViewResumed();
method onFinish (line 14) | void onFinish();
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/interfaces/SectionPresenter.java
type SectionPresenter (line 3) | public interface SectionPresenter {
method onSectionFocused (line 4) | void onSectionFocused(int sectionId);
method onSectionLongPressed (line 5) | void onSectionLongPressed(int sectionId);
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/interfaces/VideoGroupPresenter.java
type VideoGroupPresenter (line 5) | public interface VideoGroupPresenter {
method onVideoItemSelected (line 6) | void onVideoItemSelected(Video item);
method onVideoItemClicked (line 7) | void onVideoItemClicked(Video item);
method onVideoItemLongClicked (line 8) | void onVideoItemLongClicked(Video item);
method onScrollEnd (line 9) | void onScrollEnd(Video item);
method hasPendingActions (line 10) | boolean hasPendingActions();
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/service/SidebarService.java
class SidebarService (line 20) | public class SidebarService implements ProfileChangeListener {
method SidebarService (line 31) | private SidebarService(Context context) {
method instance (line 39) | public static SidebarService instance(Context context) {
method getPinnedItems (line 47) | public Collection<Video> getPinnedItems() {
method addPinnedItem (line 51) | public int addPinnedItem(Video item) {
method removePinnedItem (line 68) | public void removePinnedItem(Video item) {
method enableSection (line 73) | public void enableSection(int sectionId, boolean enabled) {
method getDefaultSections (line 109) | public Map<Integer, Integer> getDefaultSections() {
method getDefaultSectionIndex (line 113) | private int getDefaultSectionIndex(int sectionId) {
method isSectionPinned (line 131) | public boolean isSectionPinned(int sectionId) {
method getSectionIndex (line 136) | public int getSectionIndex(int sectionId) {
method renameSection (line 145) | public void renameSection(int sectionId, String newTitle) {
method moveSectionUp (line 154) | public void moveSectionUp(int sectionId) {
method moveSectionDown (line 158) | public void moveSectionDown(int sectionId) {
method canMoveSectionUp (line 162) | public boolean canMoveSectionUp(int sectionId) {
method canMoveSectionDown (line 166) | public boolean canMoveSectionDown(int sectionId) {
method canShiftSection (line 170) | private boolean canShiftSection(int sectionId, int shift) {
method shiftSection (line 180) | private void shiftSection(int sectionId, int shift) {
method findPinnedItemIndex (line 196) | private int findPinnedItemIndex(int sectionId) {
method setBootSectionId (line 210) | public void setBootSectionId(int sectionId) {
method getBootSectionId (line 216) | public int getBootSectionId() {
method enableSettingsSection (line 220) | public void enableSettingsSection(boolean enabled) {
method isSettingsSectionEnabled (line 226) | public boolean isSettingsSectionEnabled() {
method getSectionId (line 230) | private int getSectionId(Video item) {
method initSections (line 238) | private void initSections() {
method initPinnedItems (line 259) | private void initPinnedItems() {
method cleanupPinnedItems (line 266) | private void cleanupPinnedItems() {
method restoreState (line 285) | private void restoreState() {
method transferOldPinnedItems (line 306) | private void transferOldPinnedItems() {
method persistState (line 318) | public void persistState() {
method onProfileChanged (line 322) | @Override
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/AboutSettingsPresenter.java
class AboutSettingsPresenter (line 25) | public class AboutSettingsPresenter extends BasePresenter<Void> {
method AboutSettingsPresenter (line 28) | public AboutSettingsPresenter(Context context) {
method instance (line 34) | public static AboutSettingsPresenter instance(Context context) {
method show (line 38) | public void show() {
method appendAutoUpdateSwitch (line 66) | private void appendAutoUpdateSwitch(AppDialogPresenter settingsPresent...
method appendUpdateCheckButton (line 87) | private void appendUpdateCheckButton(AppDialogPresenter settingsPresen...
method appendUpdateChangelogButton (line 95) | private void appendUpdateChangelogButton(AppDialogPresenter settingsPr...
method appendLinks (line 115) | private void appendLinks(AppDialogPresenter settingsPresenter) {
method appendDonation (line 130) | private void appendDonation(AppDialogPresenter settingsPresenter) {
method appendUpdateSource (line 146) | private void appendUpdateSource(AppDialogPresenter settingsPresenter) {
method appendFeedback (line 169) | private void appendFeedback(AppDialogPresenter settingsPresenter) {
method appendInstallBridge (line 185) | private void appendInstallBridge(AppDialogPresenter settingsPresenter) {
method startBridgePresenter (line 193) | private void startBridgePresenter() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/AboutSimpleSettingsPresenter.java
class AboutSimpleSettingsPresenter (line 16) | public class AboutSimpleSettingsPresenter extends BasePresenter<Void> {
method AboutSimpleSettingsPresenter (line 19) | public AboutSimpleSettingsPresenter(Context context) {
method instance (line 25) | public static AboutSimpleSettingsPresenter instance(Context context) {
method show (line 29) | public void show() {
method appendAutoUpdateSwitch (line 45) | private void appendAutoUpdateSwitch(AppDialogPresenter settingsPresent...
method appendUpdateCheckButton (line 51) | private void appendUpdateCheckButton(AppDialogPresenter settingsPresen...
method appendInstallBridge (line 59) | private void appendInstallBridge(AppDialogPresenter settingsPresenter) {
method startBridgePresenter (line 67) | private void startBridgePresenter() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/AccountSettingsPresenter.java
class AccountSettingsPresenter (line 25) | public class AccountSettingsPresenter extends BasePresenter<Void> {
method AccountSettingsPresenter (line 31) | public AccountSettingsPresenter(Context context) {
method instance (line 36) | public static AccountSettingsPresenter instance(Context context) {
method unhold (line 46) | public void unhold() {
method show (line 50) | public void show() {
method createAndShowDialog (line 54) | private void createAndShowDialog(List<Account> accounts) {
method appendSelectAccountSection (line 68) | private void appendSelectAccountSection(List<Account> accounts, AppDia...
method appendSignOutSection (line 100) | private void appendSignOutSection(List<Account> accounts, AppDialogPre...
method appendSignInButton (line 122) | private void appendSignInButton(AppDialogPresenter settingsPresenter) {
method appendSelectAccountOnBoot (line 127) | private void appendSelectAccountOnBoot(AppDialogPresenter settingsPres...
method appendProtectAccountWithPassword (line 133) | private void appendProtectAccountWithPassword(AppDialogPresenter setti...
method appendSeparateSettings (line 143) | private void appendSeparateSettings(AppDialogPresenter settingsPresent...
method getFullName (line 152) | private String getFullName(Account account) {
method getSimpleName (line 164) | private String getSimpleName(Account account) {
method removeAccount (line 168) | private void removeAccount(Account account) {
method showAddPasswordDialog (line 173) | private void showAddPasswordDialog(AppDialogPresenter settingsPresente...
method showRemovePasswordDialog (line 187) | private void showRemovePasswordDialog(AppDialogPresenter settingsPrese...
method showCheckPasswordDialog (line 210) | public void showCheckPasswordDialog() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/AutoFrameRateSettingsPresenter.java
class AutoFrameRateSettingsPresenter (line 11) | public class AutoFrameRateSettingsPresenter extends BasePresenter<Void> {
method AutoFrameRateSettingsPresenter (line 14) | public AutoFrameRateSettingsPresenter(Context context) {
method instance (line 19) | public static AutoFrameRateSettingsPresenter instance(Context context) {
method show (line 23) | public void show() {
method show (line 27) | public void show(Runnable onFinish) {
method appendAutoFrameRateCategory (line 37) | private void appendAutoFrameRateCategory(AppDialogPresenter settingsPr...
method appendAutoFrameRatePauseCategory (line 42) | private void appendAutoFrameRatePauseCategory(AppDialogPresenter setti...
method appendAutoFrameRateModesCategory (line 47) | private void appendAutoFrameRateModesCategory(AppDialogPresenter setti...
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/BackupSettingsPresenter.java
class BackupSettingsPresenter (line 25) | public class BackupSettingsPresenter extends BasePresenter<Void> {
method BackupSettingsPresenter (line 33) | private BackupSettingsPresenter(Context context) {
method instance (line 40) | public static BackupSettingsPresenter instance(Context context) {
method unhold (line 50) | public void unhold() {
method show (line 54) | public void show() {
method showLocalRestoreDialogApi30 (line 58) | public void showLocalRestoreDialogApi30() {
method createAndShowDialog (line 64) | private void createAndShowDialog() {
method appendGDriveBackupCategory (line 73) | private void appendGDriveBackupCategory(AppDialogPresenter settingsPre...
method appendGDriveRestoreSettings (line 85) | private void appendGDriveRestoreSettings(AppDialogPresenter settingsPr...
method appendGDriveBackupSettings (line 89) | private void appendGDriveBackupSettings(AppDialogPresenter settingsPre...
method appendLocalAutoBackupOption (line 93) | private void appendLocalAutoBackupOption(List<OptionItem> options) {
method appendGDriveAutoBackupButton (line 125) | private void appendGDriveAutoBackupButton(AppDialogPresenter settingsP...
method appendGDriveMiscButtons (line 155) | private void appendGDriveMiscButtons(AppDialogPresenter settingsPresen...
method appendLocalBackupCategory (line 166) | private void appendLocalBackupCategory(AppDialogPresenter settingsPres...
method appendLocalBackupRestoreOptions (line 175) | private void appendLocalBackupRestoreOptions(List<OptionItem> options) {
method appendSubscriptionsBackupButton (line 199) | private void appendSubscriptionsBackupButton(AppDialogPresenter settin...
method showLocalRestoreDialog (line 203) | private void showLocalRestoreDialog(BackupAndRestoreManager backupMana...
method showLocalRestoreSelectorDialog (line 211) | private void showLocalRestoreSelectorDialog(List<String> backups, Back...
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/DeArrowSettingsPresenter.java
class DeArrowSettingsPresenter (line 18) | public class DeArrowSettingsPresenter extends BasePresenter<Void> {
method DeArrowSettingsPresenter (line 22) | private DeArrowSettingsPresenter(Context context) {
method instance (line 28) | public static DeArrowSettingsPresenter instance(Context context) {
method show (line 32) | public void show(Runnable onFinish) {
method show (line 42) | public void show() {
method appendThumbQuality (line 46) | private void appendThumbQuality(AppDialogPresenter settingsPresenter) {
method appendSwitches (line 63) | private void appendSwitches(AppDialogPresenter settingsPresenter) {
method appendLinks (line 89) | private void appendLinks(AppDialogPresenter settingsPresenter) {
method appendDeArrowSwitch (line 100) | private void appendDeArrowSwitch(AppDialogPresenter settingsPresenter) {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/GeneralSettingsPresenter.java
class GeneralSettingsPresenter (line 42) | public class GeneralSettingsPresenter extends BasePresenter<Void> {
method GeneralSettingsPresenter (line 57) | private GeneralSettingsPresenter(Context context) {
method instance (line 67) | public static GeneralSettingsPresenter instance(Context context) {
method show (line 71) | public void show() {
method appendEnabledSections (line 89) | private void appendEnabledSections(AppDialogPresenter settingsPresente...
method appendHideContent (line 110) | private void appendHideContent(AppDialogPresenter settingsPresenter) {
method appendContextMenuItemsCategory (line 183) | private void appendContextMenuItemsCategory(AppDialogPresenter setting...
method appendContextMenuSortingCategory (line 208) | private void appendContextMenuSortingCategory(AppDialogPresenter setti...
method showMenuItemOrderDialog (line 227) | private void showMenuItemOrderDialog(Long menuItem) {
method appendBootToSection (line 269) | private void appendBootToSection(AppDialogPresenter settingsPresenter) {
method appendAppExitCategory (line 301) | private void appendAppExitCategory(AppDialogPresenter settingsPresente...
method appendBackgroundPlaybackCategory (line 316) | private void appendBackgroundPlaybackCategory(AppDialogPresenter setti...
method appendKeyRemappingCategory (line 321) | private void appendKeyRemappingCategory(AppDialogPresenter settingsPre...
method appendScreenDimmingCategory (line 448) | private void appendScreenDimmingCategory(AppDialogPresenter settingsPr...
method appendScreenDimmingAmountCategory (line 457) | private void appendScreenDimmingAmountCategory(AppDialogPresenter sett...
method appendScreenDimmingTimeoutCategory (line 472) | @SuppressLint("StringFormatMatches")
method appendHistoryCategory (line 524) | private void appendHistoryCategory(AppDialogPresenter settingsPresente...
method appendMiscCategory (line 540) | private void appendMiscCategory(AppDialogPresenter settingsPresenter) {
method appendInternetCensorship (line 664) | private void appendInternetCensorship(AppDialogPresenter settingsPrese...
method appendProxyManager (line 674) | private void appendProxyManager(AppDialogPresenter settingsPresenter, ...
method enableChildMode (line 695) | private void enableChildMode(boolean enable) {
method showPasswordDialog (line 739) | private void showPasswordDialog(AppDialogPresenter settingsPresenter, ...
method showMasterPasswordDialog (line 761) | private void showMasterPasswordDialog(AppDialogPresenter settingsPrese...
method getMenuNames (line 783) | private Map<Long, Integer> getMenuNames() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/LanguageSettingsPresenter.java
class LanguageSettingsPresenter (line 20) | public class LanguageSettingsPresenter extends BasePresenter<Void> {
method LanguageSettingsPresenter (line 30) | public LanguageSettingsPresenter(Context context) {
method instance (line 35) | public static LanguageSettingsPresenter instance(Context context) {
method show (line 39) | public void show() {
method appendLanguageCategory (line 48) | private void appendLanguageCategory(AppDialogPresenter settingsPresent...
method appendCountryCategory (line 74) | private void appendCountryCategory(AppDialogPresenter settingsPresente...
method getSupportedLanguages (line 104) | private Map<String, String> getSupportedLanguages() {
method getSupportedCountries (line 111) | private Map<String, String> getSupportedCountries() {
FILE: common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/MainUISettingsPresenter.java
class MainUISettingsPresenter (line 23) | public class MainUISettingsPresenter extends BasePresenter<Void> {
method MainUISettingsPresenter (line 36) | private MainUISettingsPresenter(Context context) {
method instance (line 44) | public static MainUISettingsPresenter instance(Context context) {
method show (line 48) | public void show() {
method appendTopButtonsCategory (line 72) | private void appendTopButtonsCategory(AppDialogPresenter settingsPrese...
method appendColorScheme (line 91) | private void appendColorScheme(AppDialogPresenter settingsPresenter) {
method fromColorSchemes (line 97) | private List<OptionItem> fromColorSchemes(List<ColorScheme> colorSchem...
method appendCardPreviews (line 113) | private void appendCardPreviews(AppDialogPresenter settingsPresenter) {
method appendCardStyle (line 128) | private void appendCardStyle(AppDialogPresenter settingsPresenter) {
method appendCardTitleLines (line 153) | private void appendCardTitleLines(AppDialogPresenter settingsPresenter) {
method appendThumbSource (line 165) | private void appendThumbSource(AppDialogPresenter settingsPresenter) {
method appendChannelSortingCategory (line 182) | private void appendChannelSort
Copy disabled (too large)
Download .json
Condensed preview — 2868 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (16,530K chars).
[
{
"path": ".github/FUNDING.yml",
"chars": 613,
"preview": "# These are supported funding model platforms\n\ngithub: # yuliskov\npatreon: smarttube\nopen_collective: # smarttubeapp\nko_"
},
{
"path": ".github/ISSUE_TEMPLATE/1-bug_report.yml",
"chars": 2825,
"preview": "name: Bug Report\ndescription: Create a bug report to help us improve\ntitle: \"[BUG]: \"\nlabels: [bug]\n\nbody:\n - type: mar"
},
{
"path": ".github/ISSUE_TEMPLATE/2-feature-request.yml",
"chars": 1247,
"preview": "name: Feature Request\ndescription: Create a feature request for SmartTube\ntitle: '[Feature Request]: '\nlabels: ['enhance"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 390,
"preview": "blank_issues_enabled: false\ncontact_links:\n - name: Telegram group (international)\n url: http://t.me/SmartTubeEN\n "
},
{
"path": ".github/workflows/CI.yml",
"chars": 4309,
"preview": "name: Build Debug APK\n\non:\n push:\n branches: [ \"master\" ]\n workflow_dispatch:\n\njobs:\n build:\n runs-on: ubuntu-l"
},
{
"path": ".github/workflows/cleanup.yml",
"chars": 1767,
"preview": "name: Cleanup old workflow runs\r\n\r\non:\r\n schedule:\r\n - cron: '0 3 * * *'\r\n workflow_dispatch:\r\n\r\njobs:\r\n cleanup:\r"
},
{
"path": ".github/workflows/stale.yml",
"chars": 901,
"preview": "name: \"Close stale issues\"\non:\n workflow_dispatch:\n branches:\n - master\n \njobs:\n stale:\n runs-on: ubuntu-"
},
{
"path": ".github/workflows/virustotal_scan.yml",
"chars": 3301,
"preview": "name: VirusTotal Scan\r\n\r\non:\r\n release:\r\n types: [published]\r\n workflow_dispatch:\r\n inputs:\r\n release_tag:\r"
},
{
"path": ".gitignore",
"chars": 878,
"preview": "# built application files\n*.apk\n*.ap_\n\n# files for the dex VM\n*.dex\n\n# Java class files\n*.class\n\n# generated files\nbin/\n"
},
{
"path": ".gitmodules",
"chars": 207,
"preview": "[submodule \"SharedModules\"]\n\tpath = SharedModules\n\turl = https://github.com/yuliskov/SharedModules\n[submodule \"MediaServ"
},
{
"path": ".reuse/dep5",
"chars": 1282,
"preview": "Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\r\nUpstream-Name: SmartTube\r\nSource: https://gi"
},
{
"path": "LICENSE",
"chars": 1072,
"preview": "MIT License\n\nCopyright (c) 2020-present yuliskov\n\nPermission is hereby granted, free of charge, to any person obtaining\n"
},
{
"path": "README.md",
"chars": 31249,
"preview": "<p align=\"center\">\r\n <a href=\"https://f-droid.org/packages/app.smarttube.fdroid/\">\r\n <img src=\"https://fdroid.gitlab"
},
{
"path": "build.gradle",
"chars": 3162,
"preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\napply from: gradle.e"
},
{
"path": "chatkit/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "chatkit/LICENSE",
"chars": 11358,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "chatkit/build.gradle",
"chars": 1092,
"preview": "apply from: gradle.ext.sharedModulesConstants\napply plugin: 'com.android.library'\n\nandroid {\n compileSdkVersion proje"
},
{
"path": "chatkit/proguard.txt",
"chars": 167,
"preview": "# ViewHolder constructors are resolved by reflection\n-keepclassmembers class * extends com.stfalcon.chatkit.commons.View"
},
{
"path": "chatkit/src/main/AndroidManifest.xml",
"chars": 55,
"preview": "<manifest package=\"com.stfalcon.chatkit\">\n\n</manifest>\n"
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/commons/DebouncedOnClickListener.java",
"chars": 1573,
"preview": "package com.stfalcon.chatkit.commons;\r\n\r\nimport android.os.SystemClock;\r\nimport android.view.View;\r\n\r\nimport java.util.M"
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/commons/ImageLoader.java",
"chars": 1064,
"preview": "/*******************************************************************************\n * Copyright 2016 stfalcon.com\n * <p>\n "
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/commons/InputTrackingRecyclerViewAdapter.java",
"chars": 3616,
"preview": "package com.stfalcon.chatkit.commons;\r\n\r\nimport android.view.KeyEvent;\r\nimport android.view.View;\r\nimport androidx.recyc"
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/commons/Style.java",
"chars": 3288,
"preview": "/*******************************************************************************\n * Copyright 2016 stfalcon.com\n * <p>\n "
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/commons/ViewHolder.java",
"chars": 1097,
"preview": "/*******************************************************************************\n * Copyright 2016 stfalcon.com\n * <p>\n "
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/commons/models/IDialog.java",
"chars": 1156,
"preview": "/*******************************************************************************\n * Copyright 2016 stfalcon.com\n * <p>\n "
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/commons/models/IMessage.java",
"chars": 1636,
"preview": "/*******************************************************************************\n * Copyright 2016 stfalcon.com\n * <p>\n "
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/commons/models/IUser.java",
"chars": 1225,
"preview": "/*******************************************************************************\n * Copyright 2016 stfalcon.com\n * <p>\n "
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/commons/models/MessageContentType.java",
"chars": 1315,
"preview": "/*******************************************************************************\n * Copyright 2016 stfalcon.com\n * <p>\n "
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/commons/widgets/FocusFixRelativeLayout.java",
"chars": 1006,
"preview": "package com.stfalcon.chatkit.commons.widgets;\r\n\r\nimport android.content.Context;\r\nimport android.util.AttributeSet;\r\nimp"
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/commons/widgets/WrapWidthTextView.java",
"chars": 1921,
"preview": "package com.stfalcon.chatkit.commons.widgets;\r\n\r\nimport android.content.Context;\r\nimport android.text.Layout;\r\nimport an"
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/dialogs/DialogListStyle.java",
"chars": 11335,
"preview": "/*******************************************************************************\n * Copyright 2016 stfalcon.com\n * <p>\n "
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/dialogs/DialogsList.java",
"chars": 3708,
"preview": "/*******************************************************************************\n * Copyright 2016 stfalcon.com\n * <p>\n "
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/dialogs/DialogsListAdapter.java",
"chars": 24780,
"preview": "/******************************************************************************\n * Copyright 2016 stfalcon.com\n * <p>\n *"
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageHolders.java",
"chars": 48707,
"preview": "package com.stfalcon.chatkit.messages;\n\nimport android.annotation.SuppressLint;\nimport android.text.Spannable;\nimport an"
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageInput.java",
"chars": 10828,
"preview": "/*******************************************************************************\n * Copyright 2016 stfalcon.com\n * <p>\n "
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageInputStyle.java",
"chars": 12596,
"preview": "/*******************************************************************************\n * Copyright 2016 stfalcon.com\n * <p>\n "
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/messages/MessagesList.java",
"chars": 3736,
"preview": "/*******************************************************************************\n * Copyright 2016 stfalcon.com\n * <p>\n "
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/messages/MessagesListAdapter.java",
"chars": 39160,
"preview": "/*******************************************************************************\n * Copyright 2016 stfalcon.com\n * <p>\n "
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/messages/MessagesListStyle.java",
"chars": 19285,
"preview": "/*******************************************************************************\n * Copyright 2016 stfalcon.com\n * <p>\n "
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/messages/RecyclerScrollMoreListener.java",
"chars": 5149,
"preview": "/*******************************************************************************\n * Copyright 2016 stfalcon.com\n * <p>\n "
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/utils/DateFormatter.java",
"chars": 4536,
"preview": "/*******************************************************************************\n * Copyright 2016 stfalcon.com\n * <p>\n "
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/utils/RoundedImageView.java",
"chars": 9105,
"preview": "package com.stfalcon.chatkit.utils;\n\nimport android.content.Context;\nimport android.content.res.Resources;\nimport androi"
},
{
"path": "chatkit/src/main/java/com/stfalcon/chatkit/utils/ShapeImageView.java",
"chars": 2421,
"preview": "/*******************************************************************************\n * Copyright 2016 stfalcon.com\n * <p>\n "
},
{
"path": "chatkit/src/main/res/color/textchange.xml",
"chars": 420,
"preview": "<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\r\n <!--<item android:state_selected=\"true\" andro"
},
{
"path": "chatkit/src/main/res/drawable/bgchange.xml",
"chars": 442,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\r\n <item"
},
{
"path": "chatkit/src/main/res/drawable/bubble_circle.xml",
"chars": 334,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:sha"
},
{
"path": "chatkit/src/main/res/drawable/shape_incoming_message.xml",
"chars": 568,
"preview": "<!-- MODIFIED -->\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:shape=\"rectangle\">\n\n "
},
{
"path": "chatkit/src/main/res/drawable/shape_incoming_message_focused.xml",
"chars": 577,
"preview": "<!-- MODIFIED -->\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:shape=\"rectangle\">\n\n "
},
{
"path": "chatkit/src/main/res/drawable/shape_outcoming_message.xml",
"chars": 418,
"preview": "<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:shape=\"rectangle\">\n\n <corners\n a"
},
{
"path": "chatkit/src/main/res/layout/item_date_header.xml",
"chars": 252,
"preview": "<TextView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:id=\"@id/messageText\"\n android:layout"
},
{
"path": "chatkit/src/main/res/layout/item_dialog.xml",
"chars": 4451,
"preview": "<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:id=\"@id/dialogRootLayout\"\n androi"
},
{
"path": "chatkit/src/main/res/layout/item_incoming_image_message.xml",
"chars": 1790,
"preview": "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:layout_width=\"wrap_content\"\n a"
},
{
"path": "chatkit/src/main/res/layout/item_incoming_text_message.xml",
"chars": 3297,
"preview": "<!-- MOD: -->\n<!-- Android 9 message focused bug fix: RelativeLayout focusable=\"false\" -->\n<!-- Decrease space between m"
},
{
"path": "chatkit/src/main/res/layout/item_outcoming_image_message.xml",
"chars": 1385,
"preview": "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:layout_width=\"match_parent\"\n a"
},
{
"path": "chatkit/src/main/res/layout/item_outcoming_text_message.xml",
"chars": 1696,
"preview": "<!-- MODIFIED: Android 9 message focused bug fix (RelativeLayout focusable=\"false\") -->\n<RelativeLayout xmlns:android=\"h"
},
{
"path": "chatkit/src/main/res/layout/view_message_input.xml",
"chars": 1673,
"preview": "<merge xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:layout_width=\"match_parent\"\n android:la"
},
{
"path": "chatkit/src/main/res/values/attrs.xml",
"chars": 10928,
"preview": "<resources>\n\n <attr name=\"MessageInput\" format=\"reference\" />\n\n <declare-styleable name=\"MessageInput\">\n <a"
},
{
"path": "chatkit/src/main/res/values/colors.xml",
"chars": 1528,
"preview": "<resources>\n <color name=\"dark_red\">#ffcc0000</color>\n <color name=\"light_red\">#ffff4444</color>\n <color name=\""
},
{
"path": "chatkit/src/main/res/values/dimens.xml",
"chars": 1977,
"preview": "<resources>\n <dimen name=\"input_button_width\">36dp</dimen>\n <dimen name=\"input_button_height\">36dp</dimen>\n <di"
},
{
"path": "chatkit/src/main/res/values/fonts.xml",
"chars": 125,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <string name=\"font_fontFamily_medium\">sans-serif</string>\n</resou"
},
{
"path": "chatkit/src/main/res/values/ids.xml",
"chars": 1071,
"preview": "<resources>\n\n <!-- MESSAGE LIST ITEM -->\n <item name=\"bubble\" type=\"id\" />\n <item name=\"messageText\" type=\"id\" "
},
{
"path": "chatkit/src/main/res/values/strings.xml",
"chars": 14,
"preview": "<resources />\n"
},
{
"path": "chatkit/src/main/res/values/styles.xml",
"chars": 1950,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n <style name=\"ChatTheme\" parent=\"Theme.AppCompat.Light.NoActionBa"
},
{
"path": "chatkit/src/main/res/values-v21/fonts.xml",
"chars": 132,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <string name=\"font_fontFamily_medium\">sans-serif-medium</string>\n"
},
{
"path": "common/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "common/build.gradle",
"chars": 3909,
"preview": "apply from: gradle.ext.sharedModulesConstants\r\napply plugin: 'kotlin-android'\r\napply plugin: 'com.android.library'\r\n\r\nan"
},
{
"path": "common/consumer-rules.pro",
"chars": 0,
"preview": ""
},
{
"path": "common/proguard-rules.pro",
"chars": 772,
"preview": "# Add project specific ProGuard rules here.\r\n# You can control the set of applied configuration files using the\r\n# progu"
},
{
"path": "common/src/main/AndroidManifest.xml",
"chars": 4912,
"preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n package=\"com.liskovsoft.smartyoutubetv2."
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/data/BrowseSection.java",
"chars": 3159,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.data;\r\n\r\nimport androidx.annotation.Nullable;\r\n\r\nimport com.lis"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/data/Playlist.java",
"chars": 8961,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.data;\n\nimport com.liskovsoft.smartyoutubetv2.common.utils.Utils"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/data/SettingsGroup.java",
"chars": 808,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.data;\r\n\r\nimport java.util.List;\r\n\r\npublic class SettingsGroup {"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/data/SettingsItem.java",
"chars": 482,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.data;\r\n\r\npublic class SettingsItem {\r\n public final String t"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/data/SimpleMediaItem.java",
"chars": 6370,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.data;\r\n\r\nimport com.liskovsoft.mediaserviceinterfaces.data.Medi"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/data/Video.java",
"chars": 33050,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.data;\n\nimport android.content.Context;\nimport android.text.Text"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/data/VideoGroup.java",
"chars": 14218,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.data;\r\n\r\nimport com.liskovsoft.mediaserviceinterfaces.data.Chap"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/errors/CategoryEmptyError.java",
"chars": 1460,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.errors;\r\n\r\nimport android.content.Context;\r\n\r\nimport androidx.a"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/errors/ErrorFragmentData.java",
"chars": 186,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.errors;\r\n\r\npublic interface ErrorFragmentData {\r\n void onAct"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/errors/PasswordError.java",
"chars": 774,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.errors;\r\n\r\nimport android.content.Context;\r\nimport com.liskovso"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/errors/SignInError.java",
"chars": 772,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.errors;\r\n\r\nimport android.content.Context;\r\nimport com.liskovso"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/BasePlayerController.java",
"chars": 10961,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback;\r\n\r\nimport android.app.Activity;\r\nimport android.conte"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/AutoFrameRateController.java",
"chars": 16813,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.controllers;\r\n\r\nimport android.annotation.SuppressLint"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/ChatController.java",
"chars": 6677,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.controllers;\r\n\r\nimport com.liskovsoft.mediaserviceinte"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/CommentsController.java",
"chars": 9875,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.controllers;\r\n\r\nimport android.content.Context;\r\nimpor"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/HQDialogController.java",
"chars": 8851,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.controllers;\r\n\r\nimport com.liskovsoft.sharedutils.help"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/PlayerUIController.java",
"chars": 46878,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.controllers;\r\n\r\nimport android.os.Handler;\r\nimport and"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/RemoteController.java",
"chars": 23570,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.controllers;\r\n\r\nimport android.content.Context;\r\nimpor"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/SponsorBlockController.java",
"chars": 16648,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.controllers;\r\n\r\nimport androidx.annotation.NonNull;\r\ni"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/SuggestionsController.java",
"chars": 29763,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.controllers;\r\n\r\nimport android.text.TextUtils;\r\nimport"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/VideoLoaderController.java",
"chars": 39705,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.controllers;\r\n\r\nimport android.annotation.SuppressLint"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/VideoStateController.java",
"chars": 24473,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.controllers;\r\n\r\nimport com.liskovsoft.mediaserviceinte"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/listener/PlayerEngineEventListener.java",
"chars": 1883,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.listener;\r\n\r\nimport com.google.android.exoplayer2.ExoP"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/listener/PlayerEventListener.java",
"chars": 724,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.listener;\r\n\r\nimport com.liskovsoft.mediaserviceinterfa"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/listener/PlayerUiEventListener.java",
"chars": 646,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.listener;\r\n\r\nimport com.liskovsoft.smartyoutubetv2.com"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/listener/ViewEventListener.java",
"chars": 229,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.listener;\r\n\r\npublic interface ViewEventListener {\r\n "
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/manager/PlayerConstants.java",
"chars": 1479,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.manager;\r\n\r\nimport com.google.android.exoplayer2.ui.As"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/manager/PlayerEngine.java",
"chars": 1931,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.manager;\r\n\r\nimport com.liskovsoft.mediaserviceinterfac"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/manager/PlayerManager.java",
"chars": 638,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.manager;\r\n\r\nimport com.liskovsoft.smartyoutubetv2.comm"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/manager/PlayerUI.java",
"chars": 1670,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.manager;\r\n\r\nimport com.liskovsoft.smartyoutubetv2.comm"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/service/VideoStateService.java",
"chars": 7050,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.service;\r\n\r\nimport android.annotation.SuppressLint;\r\ni"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/ui/AbstractCommentsReceiver.java",
"chars": 1800,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.ui;\r\n\r\nimport android.content.Context;\r\nimport com.lis"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/ui/ChatReceiver.java",
"chars": 334,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.ui;\r\n\r\nimport com.liskovsoft.mediaserviceinterfaces.da"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/ui/ChatReceiverImpl.java",
"chars": 498,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.ui;\r\n\r\nimport com.liskovsoft.mediaserviceinterfaces.da"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/ui/CommentsReceiver.java",
"chars": 898,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.ui;\r\n\r\nimport com.liskovsoft.mediaserviceinterfaces.da"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/ui/OptionCallback.java",
"chars": 154,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.ui;\r\n\r\npublic interface OptionCallback {\r\n void onS"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/ui/OptionCategory.java",
"chars": 2886,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.ui;\r\n\r\nimport java.util.ArrayList;\r\nimport java.util.C"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/ui/OptionItem.java",
"chars": 511,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.ui;\r\n\r\npublic interface OptionItem {\r\n int getId();"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/ui/SeekBarSegment.java",
"chars": 242,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.ui;\r\n\r\nimport android.graphics.Color;\r\n\r\npublic class "
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/ui/UiOptionItem.java",
"chars": 5298,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.playback.ui;\r\n\r\nimport com.liskovsoft.smartyoutubetv2.common.ex"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/search/MediaServiceSearchTagProvider.java",
"chars": 1642,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.search;\r\n\r\nimport android.text.TextUtils;\r\n\r\nimport com.liskovs"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/search/PrefsSearchTagsProvider.java",
"chars": 625,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.search;\r\n\r\nimport com.liskovsoft.smartyoutubetv2.common.app.mod"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/search/SearchTagsProvider.java",
"chars": 358,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.search;\r\n\r\nimport com.liskovsoft.smartyoutubetv2.common.app.mod"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/search/vineyard/Option.java",
"chars": 349,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.search.vineyard;\n\npublic class Option {\n public String title"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/search/vineyard/Tag.java",
"chars": 2167,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.search.vineyard;\n\nimport android.os.Parcel;\nimport android.os.P"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/search/vineyard/User.java",
"chars": 5218,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.models.search.vineyard;\n\nimport android.os.Parcel;\nimport android.os.P"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/AddDevicePresenter.java",
"chars": 2495,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters;\r\n\r\nimport android.annotation.SuppressLint;\r\nimport android"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/AppDialogPresenter.java",
"chars": 8802,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters;\r\n\r\nimport android.annotation.SuppressLint;\r\nimport android"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/BrowsePresenter.java",
"chars": 48888,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters;\n\nimport android.annotation.SuppressLint;\nimport android.co"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/ChannelPresenter.java",
"chars": 15556,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters;\r\n\r\nimport android.annotation.SuppressLint;\r\nimport android"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/ChannelUploadsPresenter.java",
"chars": 12393,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters;\r\n\r\nimport android.annotation.SuppressLint;\r\nimport android"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/DetailsPresenter.java",
"chars": 1172,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters;\r\n\r\nimport android.annotation.SuppressLint;\r\nimport android"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/GoogleSignInPresenter.java",
"chars": 2874,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters;\r\n\r\nimport android.annotation.SuppressLint;\r\nimport android"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/PlaybackPresenter.java",
"chars": 14061,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters;\r\n\r\nimport android.annotation.SuppressLint;\r\nimport android"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/SearchPresenter.java",
"chars": 16177,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters;\r\n\r\nimport android.annotation.SuppressLint;\r\nimport android"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/SignInPresenter.java",
"chars": 2307,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters;\r\n\r\nimport android.annotation.SuppressLint;\r\nimport android"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/SplashPresenter.java",
"chars": 14057,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters;\r\n\r\nimport android.annotation.SuppressLint;\r\nimport android"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/WebBrowserPresenter.java",
"chars": 1249,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters;\r\n\r\nimport android.annotation.SuppressLint;\r\nimport android"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/YTSignInPresenter.java",
"chars": 3070,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters;\r\n\r\nimport android.annotation.SuppressLint;\r\nimport android"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/base/BasePresenter.java",
"chars": 9615,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.base;\r\n\r\nimport android.app.Activity;\r\nimport android.conte"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/ATVBridgePresenter.java",
"chars": 1429,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.dialogs;\r\n\r\nimport android.content.Context;\r\nimport com.lis"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/AccountSelectionPresenter.java",
"chars": 5348,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.dialogs;\r\n\r\nimport android.annotation.SuppressLint;\r\nimport"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/AmazonBridgePresenter.java",
"chars": 1450,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.dialogs;\r\n\r\nimport android.content.Context;\r\nimport com.lis"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/AppUpdatePresenter.java",
"chars": 6777,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.dialogs;\r\n\r\nimport android.annotation.SuppressLint;\r\nimport"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/BootDialogPresenter.java",
"chars": 1894,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.dialogs;\r\n\r\nimport android.annotation.SuppressLint;\r\nimport"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/BridgePresenter.java",
"chars": 5754,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.dialogs;\r\n\r\nimport android.app.Activity;\r\nimport android.co"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/QuickRestorePresenter.java",
"chars": 1718,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.dialogs;\r\n\r\nimport android.content.Context;\r\nimport com.lis"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/StableRestorePresenter.java",
"chars": 2256,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.dialogs;\r\n\r\nimport android.content.Context;\r\n\r\nimport com.l"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/VideoActionPresenter.java",
"chars": 2809,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.dialogs;\r\n\r\nimport android.content.Context;\r\n\r\nimport com.l"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/menu/BaseMenuPresenter.java",
"chars": 23544,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.dialogs.menu;\r\n\r\nimport android.content.Context;\r\nimport co"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/menu/ChannelUploadsMenuPresenter.java",
"chars": 6934,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.dialogs.menu;\r\n\r\nimport android.content.Context;\r\nimport co"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/menu/SectionMenuPresenter.java",
"chars": 11930,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.dialogs.menu;\r\n\r\nimport android.content.Context;\r\n\r\nimport "
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/menu/VideoMenuPresenter.java",
"chars": 48978,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.dialogs.menu;\r\n\r\nimport android.content.Context;\r\nimport co"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/menu/providers/ContextMenuManager.java",
"chars": 1148,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.dialogs.menu.providers;\r\n\r\nimport android.content.Context;\r"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/menu/providers/ContextMenuProvider.java",
"chars": 1271,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.dialogs.menu.providers;\r\n\r\nimport android.content.Context;\r"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/menu/providers/channelgroup/ChannelGroupMenuProvider.java",
"chars": 6459,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.dialogs.menu.providers.channelgroup;\r\n\r\nimport android.cont"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/menu/providers/channelgroup/ChannelGroupServiceWrapper.java",
"chars": 3506,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.dialogs.menu.providers.channelgroup;\r\n\r\nimport android.anno"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/menu/providers/channelgroup/RemoveGroupMenuProvider.java",
"chars": 1874,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.dialogs.menu.providers.channelgroup;\r\n\r\nimport android.cont"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/dialogs/menu/providers/channelgroup/RenameGroupMenuProvider.java",
"chars": 2330,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.dialogs.menu.providers.channelgroup;\r\n\r\nimport android.cont"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/interfaces/Presenter.java",
"chars": 393,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.interfaces;\r\n\r\nimport android.content.Context;\r\n\r\npublic in"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/interfaces/SectionPresenter.java",
"chars": 206,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.interfaces;\r\n\r\npublic interface SectionPresenter {\r\n voi"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/interfaces/VideoGroupPresenter.java",
"chars": 390,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.interfaces;\r\n\r\nimport com.liskovsoft.smartyoutubetv2.common"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/service/SidebarService.java",
"chars": 10684,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.service;\r\n\r\nimport android.annotation.SuppressLint;\r\nimport"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/AboutSettingsPresenter.java",
"chars": 8904,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.settings;\r\n\r\nimport android.content.Context;\r\nimport com.li"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/AboutSimpleSettingsPresenter.java",
"chars": 3449,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.settings;\r\n\r\nimport android.content.Context;\r\nimport com.li"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/AccountSettingsPresenter.java",
"chars": 9915,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.settings;\r\n\r\nimport android.annotation.SuppressLint;\r\nimpor"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/AutoFrameRateSettingsPresenter.java",
"chars": 2273,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.settings;\r\n\r\nimport android.content.Context;\r\nimport com.li"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/BackupSettingsPresenter.java",
"chars": 11259,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.settings;\r\n\r\nimport android.annotation.SuppressLint;\r\nimpor"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/DeArrowSettingsPresenter.java",
"chars": 5085,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.settings;\r\n\r\nimport android.content.Context;\r\n\r\nimport com."
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/GeneralSettingsPresenter.java",
"chars": 44725,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.settings;\r\n\r\nimport android.annotation.SuppressLint;\r\nimpor"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/LanguageSettingsPresenter.java",
"chars": 5031,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.settings;\r\n\r\nimport android.content.Context;\r\nimport com.li"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/MainUISettingsPresenter.java",
"chars": 17917,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.settings;\r\n\r\nimport android.content.Context;\r\nimport androi"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/PlayerSettingsPresenter.java",
"chars": 38585,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.settings;\r\n\r\nimport android.annotation.SuppressLint;\r\nimpor"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/RemoteControlSettingsPresenter.java",
"chars": 7176,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.settings;\r\n\r\nimport android.annotation.SuppressLint;\r\nimpor"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/SearchSettingsPresenter.java",
"chars": 5137,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.settings;\r\n\r\nimport android.content.Context;\r\nimport com.li"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/SponsorBlockSettingsPresenter.java",
"chars": 9708,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.settings;\r\n\r\nimport android.content.Context;\r\nimport androi"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/SubtitleSettingsPresenter.java",
"chars": 4380,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.settings;\r\n\r\nimport android.content.Context;\r\nimport com.li"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/presenters/settings/UIScaleSettingsPresenter.java",
"chars": 2977,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.presenters.settings;\r\n\r\nimport android.content.Context;\r\nimport com.li"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/views/AddDeviceView.java",
"chars": 153,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.views;\r\n\r\npublic interface AddDeviceView {\r\n void showCode(String u"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/views/AppDialogView.java",
"chars": 540,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.views;\r\n\r\nimport com.liskovsoft.smartyoutubetv2.common.app.models.play"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/views/AppUpdateView.java",
"chars": 97,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.views;\r\n\r\npublic interface AppUpdateView {\r\n}\r\n"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/views/BrowseView.java",
"chars": 1089,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.views;\r\n\r\nimport com.liskovsoft.smartyoutubetv2.common.app.models.data"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/views/ChannelUploadsView.java",
"chars": 279,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.views;\r\n\r\nimport com.liskovsoft.smartyoutubetv2.common.app.models.data"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/views/ChannelView.java",
"chars": 306,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.views;\r\n\r\nimport com.liskovsoft.smartyoutubetv2.common.app.models.data"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/views/DetailsView.java",
"chars": 200,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.views;\r\n\r\nimport com.liskovsoft.smartyoutubetv2.common.app.models.data"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/views/PlaybackView.java",
"chars": 346,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.views;\r\n\r\nimport com.liskovsoft.smartyoutubetv2.common.app.models.play"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/views/SearchView.java",
"chars": 601,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.views;\r\n\r\nimport com.liskovsoft.smartyoutubetv2.common.app.models.data"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/views/SignInView.java",
"chars": 168,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.views;\r\n\r\npublic interface SignInView {\r\n void showCode(String user"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/views/SplashView.java",
"chars": 180,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.views;\r\n\r\nimport android.content.Intent;\r\n\r\npublic interface SplashVie"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/views/ViewManager.java",
"chars": 18633,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.views;\r\n\r\nimport android.annotation.SuppressLint;\r\nimport android.app."
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/views/WebBrowserView.java",
"chars": 129,
"preview": "package com.liskovsoft.smartyoutubetv2.common.app.views;\r\n\r\npublic interface WebBrowserView {\r\n void loadUrl(String u"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/autoframerate/AutoFrameRateHelper.java",
"chars": 7334,
"preview": "package com.liskovsoft.smartyoutubetv2.common.autoframerate;\r\n\r\nimport android.app.Activity;\r\nimport android.content.Con"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/autoframerate/ModeSyncManager.java",
"chars": 1311,
"preview": "package com.liskovsoft.smartyoutubetv2.common.autoframerate;\r\n\r\nimport android.app.Activity;\r\nimport android.os.Handler;"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/autoframerate/internal/DisplayHolder.java",
"chars": 5143,
"preview": "package com.liskovsoft.smartyoutubetv2.common.autoframerate.internal;\n\nimport android.os.Parcel;\nimport android.os.Parce"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/autoframerate/internal/DisplaySyncHelper.java",
"chars": 19163,
"preview": "package com.liskovsoft.smartyoutubetv2.common.autoframerate.internal;\r\n\r\nimport android.content.Context;\r\nimport android"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/autoframerate/internal/UhdHelper.java",
"chars": 23953,
"preview": "package com.liskovsoft.smartyoutubetv2.common.autoframerate.internal;\n\nimport android.annotation.SuppressLint;\nimport an"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/autoframerate/internal/UhdHelperListener.java",
"chars": 1035,
"preview": "package com.liskovsoft.smartyoutubetv2.common.autoframerate.internal;\n\nimport android.view.Window;\n\n/**\n * The interface"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/exoplayer/ExoMediaSourceFactory.java",
"chars": 21131,
"preview": "package com.liskovsoft.smartyoutubetv2.common.exoplayer;\r\n\r\nimport android.annotation.SuppressLint;\r\nimport android.cont"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/exoplayer/LiveDashManifestParser.java",
"chars": 18620,
"preview": "package com.liskovsoft.smartyoutubetv2.common.exoplayer;\r\n\r\nimport android.net.Uri;\r\nimport com.google.android.exoplayer"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/exoplayer/controller/ExoPlayerController.java",
"chars": 18742,
"preview": "package com.liskovsoft.smartyoutubetv2.common.exoplayer.controller;\r\n\r\nimport android.content.Context;\r\nimport android.o"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/exoplayer/controller/PlayerView.java",
"chars": 248,
"preview": "package com.liskovsoft.smartyoutubetv2.common.exoplayer.controller;\r\n\r\nimport com.liskovsoft.smartyoutubetv2.common.app."
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/exoplayer/errors/DashDefaultLoadErrorHandlingPolicy.java",
"chars": 1652,
"preview": "package com.liskovsoft.smartyoutubetv2.common.exoplayer.errors;\r\n\r\nimport com.google.android.exoplayer2.C;\r\nimport com.g"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/exoplayer/errors/SabrDefaultLoadErrorHandlingPolicy.java",
"chars": 830,
"preview": "package com.liskovsoft.smartyoutubetv2.common.exoplayer.errors;\r\n\r\nimport com.liskovsoft.sharedutils.helpers.Helpers;\r\n\r"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/exoplayer/errors/TrackErrorFixer.java",
"chars": 8946,
"preview": "package com.liskovsoft.smartyoutubetv2.common.exoplayer.errors;\r\n\r\nimport androidx.annotation.Nullable;\r\nimport com.goog"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/exoplayer/other/DebugInfoManager.java",
"chars": 20639,
"preview": "package com.liskovsoft.smartyoutubetv2.common.exoplayer.other;\n\nimport android.annotation.SuppressLint;\nimport android.c"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/exoplayer/other/ExoPlayerInitializer.java",
"chars": 9094,
"preview": "package com.liskovsoft.smartyoutubetv2.common.exoplayer.other;\r\n\r\nimport android.content.Context;\r\nimport android.os.Bui"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/exoplayer/other/SubtitleManager.java",
"chars": 7225,
"preview": "package com.liskovsoft.smartyoutubetv2.common.exoplayer.other;\r\n\r\nimport android.content.Context;\r\nimport android.graphi"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/exoplayer/other/VideoZoomManager.java",
"chars": 1166,
"preview": "package com.liskovsoft.smartyoutubetv2.common.exoplayer.other;\r\n\r\nimport com.google.android.exoplayer2.ui.AspectRatioFra"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/exoplayer/other/VolumeBooster.java",
"chars": 2716,
"preview": "package com.liskovsoft.smartyoutubetv2.common.exoplayer.other;\r\n\r\nimport android.media.audiofx.LoudnessEnhancer;\r\nimport"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/exoplayer/selector/ExoFormatItem.java",
"chars": 13876,
"preview": "package com.liskovsoft.smartyoutubetv2.common.exoplayer.selector;\r\n\r\nimport android.text.TextUtils;\r\n\r\nimport androidx.a"
},
{
"path": "common/src/main/java/com/liskovsoft/smartyoutubetv2/common/exoplayer/selector/FormatItem.java",
"chars": 3294,
"preview": "package com.liskovsoft.smartyoutubetv2.common.exoplayer.selector;\r\n\r\nimport androidx.annotation.NonNull;\r\n\r\nimport com.l"
}
]
// ... and 2668 more files (download for full content)
About this extraction
This page contains the full source code of the yuliskov/SmartTube GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 2868 files (30.3 MB), approximately 4.1M tokens, and a symbol index with 19867 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.