Repository files navigation

Feature module template project

Template project for starting android development. Although it grew to be more of a showcase of different feature implementations, most of which are contained on Home screen:

  • Passing navigation arguments forward and backward.
  • Animated splash screen.
  • Linters in Github actions.
  • Gradle tasks and convention plugins.
  • Exoplayer implementation with custom controls overlay.
  • In-app camera implementation.
  • Barcode scanning with ML Kit.
  • Custom CompositionLocal for colors (partly shown on Feature tab).
  • SMS authentication with firebase in sms-authentication branch.
  • Connecting to Wi-Fi networks.
  • Multiple app themes.

Screenshots

Splash screen

splash

Initial functionality

Exoplayer video playback

exoplayer

Themes

themes

Quick overview

FeatureShort description
ArchitectureFeature modules
DIHilt
UICompose and MVI
NavigationCompose navigation

Architecture

architecture

Feature modules, each divided into two parts: api and impl.

Api modules only contain logic for navigating to this module, and don't rely on other modules. It's preferable to put all logic into objects with Destination suffix, such as HomeDestination. Members naming inside the Destination object is not enforced (but can be via an interface), however this template uses ROUTE constant for adding the route to the NavGraph, and constructRoute() for returning a string with arguments to be used for navigating to this route.

Impl modules contain screens, implementation for the navigation, and can rely on other api modules for navigating to them.

Naming scheme of modules and packages is camelCase (homeApi, com.package.homeImpl).

UI

Single Activity containing bottom navigation bar and Compose screens.

UI architecture: MVVM with MVI. State is passed to UI, Events are passed to ViewModel. No Effects.

Custom CompositionLocalProvider was added to AppTheme for providing AppColors (link). Provided colors can be configured as needed by the design. Moreover it's possible to add other design components, like fonts, and thus mostly replace MaterialTheme.

BaseVM is a base class for ViewModels.

Navigation

Compose navigation. Routes are created with the help of api modules.

Singleton NavManager is used to abstract navigation and move navigation command triggering to ViewModels. Stream of navigation commands is observed in the module responsible for navigation (currently :app).

Gradle

Version catalogs are used for version management.

Convention plugins are added in buildSrc for easier management of build.gradle files. Main plugins are:

  • convention-linters - adds and configures detekt and ktlint plugins.
  • convention-android-library - uses convention-linters, sets up general settings in android{} extension, which are shared with all android library modules. Mainly used for core and api feature modules.
  • convention-feature-module - uses convention-android-library, sets up additional dependencies (Hilt, Navigation, Compose), which are useful for all impl feature modules.

Convention plugins introduce some issues when using version catalogs in them, especially in plugins{} blocks, so some workarounds were applied where possible.

In addition to Android Studio's module creation, a custom gradle task createLibraryModule was added, that automatically adds build.gradle with convention plugins to the new module.

Source: CreateAndroidModuleTask.kt. Example, creating module 'module1' in subdirectory 'feature':

./gradlew createLibraryModule --name :feature:module1

Another gradle task renamePackage can be used to quickly rename packages, references to them, and directories. There is also renamePackageForce version, which can overwrite existing files when moving directories. Warning: this task modifies files irreversibly, so caution should be exercised.

Source: RenamePackageTask.kt. Example usage:

./gradlew renamePackage --from com.featuremodule --to my.new.package

Configuration for all custom tasks can be found in root build.gradle.kts.

Attribution

Fox vector icon is made by UIcons

About

Testing ground for trying different Android features

Resources

Stars

0 stars

Watchers

1 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Feature module template project

Template project for starting android development. Although it grew to be more of a showcase of different feature implementations, most of which are contained on Home screen:

  • Passing navigation arguments forward and backward.
  • Animated splash screen.
  • Linters in Github actions.
  • Gradle tasks and convention plugins.
  • Exoplayer implementation with custom controls overlay.
  • In-app camera implementation.
  • Barcode scanning with ML Kit.
  • Custom CompositionLocal for colors (partly shown on Feature tab).
  • SMS authentication with firebase in sms-authentication branch.
  • Connecting to Wi-Fi networks.
  • Multiple app themes.

Screenshots

Splash screen

splash

Initial functionality

Exoplayer video playback

exoplayer

Themes

themes

Quick overview

FeatureShort description
ArchitectureFeature modules
DIHilt
UICompose and MVI
NavigationCompose navigation

Architecture

architecture

Feature modules, each divided into two parts: api and impl.

Api modules only contain logic for navigating to this module, and don't rely on other modules. It's preferable to put all logic into objects with Destination suffix, such as HomeDestination. Members naming inside the Destination object is not enforced (but can be via an interface), however this template uses ROUTE constant for adding the route to the NavGraph, and constructRoute() for returning a string with arguments to be used for navigating to this route.

Impl modules contain screens, implementation for the navigation, and can rely on other api modules for navigating to them.

Naming scheme of modules and packages is camelCase (homeApi, com.package.homeImpl).

UI

Single Activity containing bottom navigation bar and Compose screens.

UI architecture: MVVM with MVI. State is passed to UI, Events are passed to ViewModel. No Effects.

Custom CompositionLocalProvider was added to AppTheme for providing AppColors (link). Provided colors can be configured as needed by the design. Moreover it's possible to add other design components, like fonts, and thus mostly replace MaterialTheme.

BaseVM is a base class for ViewModels.

Navigation

Compose navigation. Routes are created with the help of api modules.

Singleton NavManager is used to abstract navigation and move navigation command triggering to ViewModels. Stream of navigation commands is observed in the module responsible for navigation (currently :app).

Gradle

Version catalogs are used for version management.

Convention plugins are added in buildSrc for easier management of build.gradle files. Main plugins are:

  • convention-linters - adds and configures detekt and ktlint plugins.
  • convention-android-library - uses convention-linters, sets up general settings in android{} extension, which are shared with all android library modules. Mainly used for core and api feature modules.
  • convention-feature-module - uses convention-android-library, sets up additional dependencies (Hilt, Navigation, Compose), which are useful for all impl feature modules.

Convention plugins introduce some issues when using version catalogs in them, especially in plugins{} blocks, so some workarounds were applied where possible.

In addition to Android Studio's module creation, a custom gradle task createLibraryModule was added, that automatically adds build.gradle with convention plugins to the new module.

Source: CreateAndroidModuleTask.kt. Example, creating module 'module1' in subdirectory 'feature':

./gradlew createLibraryModule --name :feature:module1

Another gradle task renamePackage can be used to quickly rename packages, references to them, and directories. There is also renamePackageForce version, which can overwrite existing files when moving directories. Warning: this task modifies files irreversibly, so caution should be exercised.

Source: RenamePackageTask.kt. Example usage:

./gradlew renamePackage --from com.featuremodule --to my.new.package

Configuration for all custom tasks can be found in root build.gradle.kts.

Attribution

Fox vector icon is made by UIcons

About

Testing ground for trying different Android features

Resources

Stars

0 stars

Watchers

1 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Feature module template project

Template project for starting android development. Although it grew to be more of a showcase of different feature implementations, most of which are contained on Home screen:

  • Passing navigation arguments forward and backward.
  • Animated splash screen.
  • Linters in Github actions.
  • Gradle tasks and convention plugins.
  • Exoplayer implementation with custom controls overlay.
  • In-app camera implementation.
  • Barcode scanning with ML Kit.
  • Custom CompositionLocal for colors (partly shown on Feature tab).
  • SMS authentication with firebase in sms-authentication branch.
  • Connecting to Wi-Fi networks.
  • Multiple app themes.

Screenshots

Splash screen

splash

Initial functionality

Exoplayer video playback

exoplayer

Themes

themes

Quick overview

FeatureShort description
ArchitectureFeature modules
DIHilt
UICompose and MVI
NavigationCompose navigation

Architecture

architecture

Feature modules, each divided into two parts: api and impl.

Api modules only contain logic for navigating to this module, and don't rely on other modules. It's preferable to put all logic into objects with Destination suffix, such as HomeDestination. Members naming inside the Destination object is not enforced (but can be via an interface), however this template uses ROUTE constant for adding the route to the NavGraph, and constructRoute() for returning a string with arguments to be used for navigating to this route.

Impl modules contain screens, implementation for the navigation, and can rely on other api modules for navigating to them.

Naming scheme of modules and packages is camelCase (homeApi, com.package.homeImpl).

UI

Single Activity containing bottom navigation bar and Compose screens.

UI architecture: MVVM with MVI. State is passed to UI, Events are passed to ViewModel. No Effects.

Custom CompositionLocalProvider was added to AppTheme for providing AppColors (link). Provided colors can be configured as needed by the design. Moreover it's possible to add other design components, like fonts, and thus mostly replace MaterialTheme.

BaseVM is a base class for ViewModels.

Navigation

Compose navigation. Routes are created with the help of api modules.

Singleton NavManager is used to abstract navigation and move navigation command triggering to ViewModels. Stream of navigation commands is observed in the module responsible for navigation (currently :app).

Gradle

Version catalogs are used for version management.

Convention plugins are added in buildSrc for easier management of build.gradle files. Main plugins are:

  • convention-linters - adds and configures detekt and ktlint plugins.
  • convention-android-library - uses convention-linters, sets up general settings in android{} extension, which are shared with all android library modules. Mainly used for core and api feature modules.
  • convention-feature-module - uses convention-android-library, sets up additional dependencies (Hilt, Navigation, Compose), which are useful for all impl feature modules.

Convention plugins introduce some issues when using version catalogs in them, especially in plugins{} blocks, so some workarounds were applied where possible.

In addition to Android Studio's module creation, a custom gradle task createLibraryModule was added, that automatically adds build.gradle with convention plugins to the new module.

Source: CreateAndroidModuleTask.kt. Example, creating module 'module1' in subdirectory 'feature':

./gradlew createLibraryModule --name :feature:module1

Another gradle task renamePackage can be used to quickly rename packages, references to them, and directories. There is also renamePackageForce version, which can overwrite existing files when moving directories. Warning: this task modifies files irreversibly, so caution should be exercised.

Source: RenamePackageTask.kt. Example usage:

./gradlew renamePackage --from com.featuremodule --to my.new.package

Configuration for all custom tasks can be found in root build.gradle.kts.

Attribution

Fox vector icon is made by UIcons

About

Testing ground for trying different Android features

Resources

Stars

0 stars

Watchers

1 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Feature module template project

Template project for starting android development. Although it grew to be more of a showcase of different feature implementations, most of which are contained on Home screen:

  • Passing navigation arguments forward and backward.
  • Animated splash screen.
  • Linters in Github actions.
  • Gradle tasks and convention plugins.
  • Exoplayer implementation with custom controls overlay.
  • In-app camera implementation.
  • Barcode scanning with ML Kit.
  • Custom CompositionLocal for colors (partly shown on Feature tab).
  • SMS authentication with firebase in sms-authentication branch.
  • Connecting to Wi-Fi networks.
  • Multiple app themes.

Screenshots

Splash screen

splash

Initial functionality

Exoplayer video playback

exoplayer

Themes

themes

Quick overview

FeatureShort description
ArchitectureFeature modules
DIHilt
UICompose and MVI
NavigationCompose navigation

Architecture

architecture

Feature modules, each divided into two parts: api and impl.

Api modules only contain logic for navigating to this module, and don't rely on other modules. It's preferable to put all logic into objects with Destination suffix, such as HomeDestination. Members naming inside the Destination object is not enforced (but can be via an interface), however this template uses ROUTE constant for adding the route to the NavGraph, and constructRoute() for returning a string with arguments to be used for navigating to this route.

Impl modules contain screens, implementation for the navigation, and can rely on other api modules for navigating to them.

Naming scheme of modules and packages is camelCase (homeApi, com.package.homeImpl).

UI

Single Activity containing bottom navigation bar and Compose screens.

UI architecture: MVVM with MVI. State is passed to UI, Events are passed to ViewModel. No Effects.

Custom CompositionLocalProvider was added to AppTheme for providing AppColors (link). Provided colors can be configured as needed by the design. Moreover it's possible to add other design components, like fonts, and thus mostly replace MaterialTheme.

BaseVM is a base class for ViewModels.

Navigation

Compose navigation. Routes are created with the help of api modules.

Singleton NavManager is used to abstract navigation and move navigation command triggering to ViewModels. Stream of navigation commands is observed in the module responsible for navigation (currently :app).

Gradle

Version catalogs are used for version management.

Convention plugins are added in buildSrc for easier management of build.gradle files. Main plugins are:

  • convention-linters - adds and configures detekt and ktlint plugins.
  • convention-android-library - uses convention-linters, sets up general settings in android{} extension, which are shared with all android library modules. Mainly used for core and api feature modules.
  • convention-feature-module - uses convention-android-library, sets up additional dependencies (Hilt, Navigation, Compose), which are useful for all impl feature modules.

Convention plugins introduce some issues when using version catalogs in them, especially in plugins{} blocks, so some workarounds were applied where possible.

In addition to Android Studio's module creation, a custom gradle task createLibraryModule was added, that automatically adds build.gradle with convention plugins to the new module.

Source: CreateAndroidModuleTask.kt. Example, creating module 'module1' in subdirectory 'feature':

./gradlew createLibraryModule --name :feature:module1

Another gradle task renamePackage can be used to quickly rename packages, references to them, and directories. There is also renamePackageForce version, which can overwrite existing files when moving directories. Warning: this task modifies files irreversibly, so caution should be exercised.

Source: RenamePackageTask.kt. Example usage:

./gradlew renamePackage --from com.featuremodule --to my.new.package

Configuration for all custom tasks can be found in root build.gradle.kts.

Attribution

Fox vector icon is made by UIcons

About

Testing ground for trying different Android features

Resources

Stars

0 stars

Watchers

1 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Feature module template project

Template project for starting android development. Although it grew to be more of a showcase of different feature implementations, most of which are contained on Home screen:

  • Passing navigation arguments forward and backward.
  • Animated splash screen.
  • Linters in Github actions.
  • Gradle tasks and convention plugins.
  • Exoplayer implementation with custom controls overlay.
  • In-app camera implementation.
  • Barcode scanning with ML Kit.
  • Custom CompositionLocal for colors (partly shown on Feature tab).
  • SMS authentication with firebase in sms-authentication branch.
  • Connecting to Wi-Fi networks.
  • Multiple app themes.

Screenshots

Splash screen

splash

Initial functionality

Exoplayer video playback

exoplayer

Themes

themes

Quick overview

FeatureShort description
ArchitectureFeature modules
DIHilt
UICompose and MVI
NavigationCompose navigation

Architecture

architecture

Feature modules, each divided into two parts: api and impl.

Api modules only contain logic for navigating to this module, and don't rely on other modules. It's preferable to put all logic into objects with Destination suffix, such as HomeDestination. Members naming inside the Destination object is not enforced (but can be via an interface), however this template uses ROUTE constant for adding the route to the NavGraph, and constructRoute() for returning a string with arguments to be used for navigating to this route.

Impl modules contain screens, implementation for the navigation, and can rely on other api modules for navigating to them.

Naming scheme of modules and packages is camelCase (homeApi, com.package.homeImpl).

UI

Single Activity containing bottom navigation bar and Compose screens.

UI architecture: MVVM with MVI. State is passed to UI, Events are passed to ViewModel. No Effects.

Custom CompositionLocalProvider was added to AppTheme for providing AppColors (link). Provided colors can be configured as needed by the design. Moreover it's possible to add other design components, like fonts, and thus mostly replace MaterialTheme.

BaseVM is a base class for ViewModels.

Navigation

Compose navigation. Routes are created with the help of api modules.

Singleton NavManager is used to abstract navigation and move navigation command triggering to ViewModels. Stream of navigation commands is observed in the module responsible for navigation (currently :app).

Gradle

Version catalogs are used for version management.

Convention plugins are added in buildSrc for easier management of build.gradle files. Main plugins are:

  • convention-linters - adds and configures detekt and ktlint plugins.
  • convention-android-library - uses convention-linters, sets up general settings in android{} extension, which are shared with all android library modules. Mainly used for core and api feature modules.
  • convention-feature-module - uses convention-android-library, sets up additional dependencies (Hilt, Navigation, Compose), which are useful for all impl feature modules.

Convention plugins introduce some issues when using version catalogs in them, especially in plugins{} blocks, so some workarounds were applied where possible.

In addition to Android Studio's module creation, a custom gradle task createLibraryModule was added, that automatically adds build.gradle with convention plugins to the new module.

Source: CreateAndroidModuleTask.kt. Example, creating module 'module1' in subdirectory 'feature':

./gradlew createLibraryModule --name :feature:module1

Another gradle task renamePackage can be used to quickly rename packages, references to them, and directories. There is also renamePackageForce version, which can overwrite existing files when moving directories. Warning: this task modifies files irreversibly, so caution should be exercised.

Source: RenamePackageTask.kt. Example usage:

./gradlew renamePackage --from com.featuremodule --to my.new.package

Configuration for all custom tasks can be found in root build.gradle.kts.

Attribution

Fox vector icon is made by UIcons

About

Testing ground for trying different Android features

Resources

Stars

0 stars

Watchers

1 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Feature module template project

Template project for starting android development. Although it grew to be more of a showcase of different feature implementations, most of which are contained on Home screen:

  • Passing navigation arguments forward and backward.
  • Animated splash screen.
  • Linters in Github actions.
  • Gradle tasks and convention plugins.
  • Exoplayer implementation with custom controls overlay.
  • In-app camera implementation.
  • Barcode scanning with ML Kit.
  • Custom CompositionLocal for colors (partly shown on Feature tab).
  • SMS authentication with firebase in sms-authentication branch.
  • Connecting to Wi-Fi networks.
  • Multiple app themes.

Screenshots

Splash screen

splash

Initial functionality

Exoplayer video playback

exoplayer

Themes

themes

Quick overview

FeatureShort description
ArchitectureFeature modules
DIHilt
UICompose and MVI
NavigationCompose navigation

Architecture

architecture

Feature modules, each divided into two parts: api and impl.

Api modules only contain logic for navigating to this module, and don't rely on other modules. It's preferable to put all logic into objects with Destination suffix, such as HomeDestination. Members naming inside the Destination object is not enforced (but can be via an interface), however this template uses ROUTE constant for adding the route to the NavGraph, and constructRoute() for returning a string with arguments to be used for navigating to this route.

Impl modules contain screens, implementation for the navigation, and can rely on other api modules for navigating to them.

Naming scheme of modules and packages is camelCase (homeApi, com.package.homeImpl).

UI

Single Activity containing bottom navigation bar and Compose screens.

UI architecture: MVVM with MVI. State is passed to UI, Events are passed to ViewModel. No Effects.

Custom CompositionLocalProvider was added to AppTheme for providing AppColors (link). Provided colors can be configured as needed by the design. Moreover it's possible to add other design components, like fonts, and thus mostly replace MaterialTheme.

BaseVM is a base class for ViewModels.

Navigation

Compose navigation. Routes are created with the help of api modules.

Singleton NavManager is used to abstract navigation and move navigation command triggering to ViewModels. Stream of navigation commands is observed in the module responsible for navigation (currently :app).

Gradle

Version catalogs are used for version management.

Convention plugins are added in buildSrc for easier management of build.gradle files. Main plugins are:

  • convention-linters - adds and configures detekt and ktlint plugins.
  • convention-android-library - uses convention-linters, sets up general settings in android{} extension, which are shared with all android library modules. Mainly used for core and api feature modules.
  • convention-feature-module - uses convention-android-library, sets up additional dependencies (Hilt, Navigation, Compose), which are useful for all impl feature modules.

Convention plugins introduce some issues when using version catalogs in them, especially in plugins{} blocks, so some workarounds were applied where possible.

In addition to Android Studio's module creation, a custom gradle task createLibraryModule was added, that automatically adds build.gradle with convention plugins to the new module.

Source: CreateAndroidModuleTask.kt. Example, creating module 'module1' in subdirectory 'feature':

./gradlew createLibraryModule --name :feature:module1

Another gradle task renamePackage can be used to quickly rename packages, references to them, and directories. There is also renamePackageForce version, which can overwrite existing files when moving directories. Warning: this task modifies files irreversibly, so caution should be exercised.

Source: RenamePackageTask.kt. Example usage:

./gradlew renamePackage --from com.featuremodule --to my.new.package

Configuration for all custom tasks can be found in root build.gradle.kts.

Attribution

Fox vector icon is made by UIcons

About

Testing ground for trying different Android features

Resources

Stars

0 stars

Watchers

1 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Feature module template project

Template project for starting android development. Although it grew to be more of a showcase of different feature implementations, most of which are contained on Home screen:

  • Passing navigation arguments forward and backward.
  • Animated splash screen.
  • Linters in Github actions.
  • Gradle tasks and convention plugins.
  • Exoplayer implementation with custom controls overlay.
  • In-app camera implementation.
  • Barcode scanning with ML Kit.
  • Custom CompositionLocal for colors (partly shown on Feature tab).
  • SMS authentication with firebase in sms-authentication branch.
  • Connecting to Wi-Fi networks.
  • Multiple app themes.

Screenshots

Splash screen

splash

Initial functionality

Exoplayer video playback

exoplayer

Themes

themes

Quick overview

FeatureShort description
ArchitectureFeature modules
DIHilt
UICompose and MVI
NavigationCompose navigation

Architecture

architecture

Feature modules, each divided into two parts: api and impl.

Api modules only contain logic for navigating to this module, and don't rely on other modules. It's preferable to put all logic into objects with Destination suffix, such as HomeDestination. Members naming inside the Destination object is not enforced (but can be via an interface), however this template uses ROUTE constant for adding the route to the NavGraph, and constructRoute() for returning a string with arguments to be used for navigating to this route.

Impl modules contain screens, implementation for the navigation, and can rely on other api modules for navigating to them.

Naming scheme of modules and packages is camelCase (homeApi, com.package.homeImpl).

UI

Single Activity containing bottom navigation bar and Compose screens.

UI architecture: MVVM with MVI. State is passed to UI, Events are passed to ViewModel. No Effects.

Custom CompositionLocalProvider was added to AppTheme for providing AppColors (link). Provided colors can be configured as needed by the design. Moreover it's possible to add other design components, like fonts, and thus mostly replace MaterialTheme.

BaseVM is a base class for ViewModels.

Navigation

Compose navigation. Routes are created with the help of api modules.

Singleton NavManager is used to abstract navigation and move navigation command triggering to ViewModels. Stream of navigation commands is observed in the module responsible for navigation (currently :app).

Gradle

Version catalogs are used for version management.

Convention plugins are added in buildSrc for easier management of build.gradle files. Main plugins are:

  • convention-linters - adds and configures detekt and ktlint plugins.
  • convention-android-library - uses convention-linters, sets up general settings in android{} extension, which are shared with all android library modules. Mainly used for core and api feature modules.
  • convention-feature-module - uses convention-android-library, sets up additional dependencies (Hilt, Navigation, Compose), which are useful for all impl feature modules.

Convention plugins introduce some issues when using version catalogs in them, especially in plugins{} blocks, so some workarounds were applied where possible.

In addition to Android Studio's module creation, a custom gradle task createLibraryModule was added, that automatically adds build.gradle with convention plugins to the new module.

Source: CreateAndroidModuleTask.kt. Example, creating module 'module1' in subdirectory 'feature':

./gradlew createLibraryModule --name :feature:module1

Another gradle task renamePackage can be used to quickly rename packages, references to them, and directories. There is also renamePackageForce version, which can overwrite existing files when moving directories. Warning: this task modifies files irreversibly, so caution should be exercised.

Source: RenamePackageTask.kt. Example usage:

./gradlew renamePackage --from com.featuremodule --to my.new.package

Configuration for all custom tasks can be found in root build.gradle.kts.

Attribution

Fox vector icon is made by UIcons

About

Testing ground for trying different Android features

Resources

Stars

0 stars

Watchers

1 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Feature module template project

Template project for starting android development. Although it grew to be more of a showcase of different feature implementations, most of which are contained on Home screen:

  • Passing navigation arguments forward and backward.
  • Animated splash screen.
  • Linters in Github actions.
  • Gradle tasks and convention plugins.
  • Exoplayer implementation with custom controls overlay.
  • In-app camera implementation.
  • Barcode scanning with ML Kit.
  • Custom CompositionLocal for colors (partly shown on Feature tab).
  • SMS authentication with firebase in sms-authentication branch.
  • Connecting to Wi-Fi networks.
  • Multiple app themes.

Screenshots

Splash screen

splash

Initial functionality

Exoplayer video playback

exoplayer

Themes

themes

Quick overview

FeatureShort description
ArchitectureFeature modules
DIHilt
UICompose and MVI
NavigationCompose navigation

Architecture

architecture

Feature modules, each divided into two parts: api and impl.

Api modules only contain logic for navigating to this module, and don't rely on other modules. It's preferable to put all logic into objects with Destination suffix, such as HomeDestination. Members naming inside the Destination object is not enforced (but can be via an interface), however this template uses ROUTE constant for adding the route to the NavGraph, and constructRoute() for returning a string with arguments to be used for navigating to this route.

Impl modules contain screens, implementation for the navigation, and can rely on other api modules for navigating to them.

Naming scheme of modules and packages is camelCase (homeApi, com.package.homeImpl).

UI

Single Activity containing bottom navigation bar and Compose screens.

UI architecture: MVVM with MVI. State is passed to UI, Events are passed to ViewModel. No Effects.

Custom CompositionLocalProvider was added to AppTheme for providing AppColors (link). Provided colors can be configured as needed by the design. Moreover it's possible to add other design components, like fonts, and thus mostly replace MaterialTheme.

BaseVM is a base class for ViewModels.

Navigation

Compose navigation. Routes are created with the help of api modules.

Singleton NavManager is used to abstract navigation and move navigation command triggering to ViewModels. Stream of navigation commands is observed in the module responsible for navigation (currently :app).

Gradle

Version catalogs are used for version management.

Convention plugins are added in buildSrc for easier management of build.gradle files. Main plugins are:

  • convention-linters - adds and configures detekt and ktlint plugins.
  • convention-android-library - uses convention-linters, sets up general settings in android{} extension, which are shared with all android library modules. Mainly used for core and api feature modules.
  • convention-feature-module - uses convention-android-library, sets up additional dependencies (Hilt, Navigation, Compose), which are useful for all impl feature modules.

Convention plugins introduce some issues when using version catalogs in them, especially in plugins{} blocks, so some workarounds were applied where possible.

In addition to Android Studio's module creation, a custom gradle task createLibraryModule was added, that automatically adds build.gradle with convention plugins to the new module.

Source: CreateAndroidModuleTask.kt. Example, creating module 'module1' in subdirectory 'feature':

./gradlew createLibraryModule --name :feature:module1

Another gradle task renamePackage can be used to quickly rename packages, references to them, and directories. There is also renamePackageForce version, which can overwrite existing files when moving directories. Warning: this task modifies files irreversibly, so caution should be exercised.

Source: RenamePackageTask.kt. Example usage:

./gradlew renamePackage --from com.featuremodule --to my.new.package

Configuration for all custom tasks can be found in root build.gradle.kts.

Attribution

Fox vector icon is made by UIcons

About

Testing ground for trying different Android features

Resources

Stars

0 stars

Watchers

1 watching

Forks

Used by

Contributors

Languages