├── .config └── detekt.yml ├── .github ├── CODEOWNERS └── workflows │ └── compile-and-check.yml ├── .gitignore ├── .idea ├── .gitignore ├── .name ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── gradle.xml ├── misc.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── xmartlabs │ │ └── typednavigation │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── xmartlabs │ │ │ └── typednavigation │ │ │ ├── App.kt │ │ │ ├── MainActivity.kt │ │ │ └── ui │ │ │ ├── hiltExapmle │ │ │ ├── HiltExample.kt │ │ │ └── HiltExampleViewModel.kt │ │ │ └── theme │ │ │ ├── Color.kt │ │ │ ├── Shape.kt │ │ │ ├── Theme.kt │ │ │ └── Type.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── values-night │ │ └── themes.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ └── test │ └── java │ └── com │ └── xmartlabs │ └── typednavigation │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── jitpack.yml ├── settings.gradle └── typednavigation ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src ├── androidTest └── java │ └── com │ └── xmartlabs │ └── typednavigation │ └── ExampleInstrumentedTest.kt ├── main ├── AndroidManifest.xml └── java │ └── com │ └── xmartlabs │ └── typednavigation │ ├── NavGraphBuilderExtensions.kt │ ├── NullableTypes.kt │ ├── TypedNavigation.kt │ ├── TypedNavigationInterface.kt │ └── TypedNavigationInterfaceExtensions.kt └── test └── java └── com └── xmartlabs └── typednavigation ├── TestRouter.kt └── UnitTest.kt /.config/detekt.yml: -------------------------------------------------------------------------------- 1 | build: 2 | maxIssues: 0 3 | excludeCorrectable: false 4 | weights: 5 | # complexity: 2 6 | # LongParameterList: 1 7 | # style: 1 8 | # comments: 1 9 | 10 | config: 11 | validation: true 12 | warningsAsErrors: false 13 | # when writing own rules with new properties, exclude the property path e.g.: 'my_rule_set,.*>.*>[my_property]' 14 | excludes: '' 15 | 16 | processors: 17 | active: true 18 | exclude: 19 | - 'DetektProgressListener' 20 | # - 'KtFileCountProcessor' 21 | # - 'PackageCountProcessor' 22 | # - 'ClassCountProcessor' 23 | # - 'FunctionCountProcessor' 24 | # - 'PropertyCountProcessor' 25 | # - 'ProjectComplexityProcessor' 26 | # - 'ProjectCognitiveComplexityProcessor' 27 | # - 'ProjectLLOCProcessor' 28 | # - 'ProjectCLOCProcessor' 29 | # - 'ProjectLOCProcessor' 30 | # - 'ProjectSLOCProcessor' 31 | # - 'LicenseHeaderLoaderExtension' 32 | 33 | console-reports: 34 | active: true 35 | exclude: 36 | - 'ProjectStatisticsReport' 37 | - 'ComplexityReport' 38 | - 'NotificationReport' 39 | # - 'FindingsReport' 40 | - 'FileBasedFindingsReport' 41 | - 'LiteFindingsReport' 42 | 43 | output-reports: 44 | active: true 45 | exclude: 46 | # - 'TxtOutputReport' 47 | # - 'XmlOutputReport' 48 | # - 'HtmlOutputReport' 49 | 50 | comments: 51 | active: true 52 | AbsentOrWrongFileLicense: 53 | active: false 54 | licenseTemplateFile: 'license.template' 55 | licenseTemplateIsRegex: false 56 | CommentOverPrivateFunction: 57 | active: false 58 | CommentOverPrivateProperty: 59 | active: false 60 | DeprecatedBlockTag: 61 | active: false 62 | EndOfSentenceFormat: 63 | active: false 64 | endOfSentenceFormat: '([.?!][ \t\n\r\f<])|([.?!:]$)' 65 | UndocumentedPublicClass: 66 | active: false 67 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 68 | searchInNestedClass: true 69 | searchInInnerClass: true 70 | searchInInnerObject: true 71 | searchInInnerInterface: true 72 | UndocumentedPublicFunction: 73 | active: false 74 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 75 | UndocumentedPublicProperty: 76 | active: false 77 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 78 | 79 | complexity: 80 | active: true 81 | ComplexCondition: 82 | active: true 83 | threshold: 4 84 | ComplexInterface: 85 | active: false 86 | threshold: 10 87 | includeStaticDeclarations: false 88 | includePrivateDeclarations: false 89 | ComplexMethod: 90 | active: true 91 | threshold: 15 92 | ignoreSingleWhenExpression: false 93 | ignoreSimpleWhenEntries: false 94 | ignoreNestingFunctions: false 95 | nestingFunctions: 96 | - 'also' 97 | - 'apply' 98 | - 'forEach' 99 | - 'isNotNull' 100 | - 'ifNull' 101 | - 'let' 102 | - 'run' 103 | - 'use' 104 | - 'with' 105 | LabeledExpression: 106 | active: false 107 | ignoredLabels: [] 108 | LargeClass: 109 | active: true 110 | threshold: 600 111 | LongMethod: 112 | active: true 113 | threshold: 60 114 | LongParameterList: 115 | active: true 116 | functionThreshold: 6 117 | constructorThreshold: 7 118 | ignoreDefaultParameters: false 119 | ignoreDataClasses: true 120 | # ignoreAnnotatedParameter: [] 121 | MethodOverloading: 122 | active: false 123 | threshold: 6 124 | NamedArguments: 125 | active: false 126 | threshold: 3 127 | NestedBlockDepth: 128 | active: true 129 | threshold: 4 130 | ReplaceSafeCallChainWithRun: 131 | active: false 132 | StringLiteralDuplication: 133 | active: false 134 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 135 | threshold: 3 136 | ignoreAnnotation: true 137 | excludeStringsWithLessThan5Characters: true 138 | ignoreStringsRegex: '$^' 139 | TooManyFunctions: 140 | active: true 141 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 142 | thresholdInFiles: 100 143 | thresholdInClasses: 11 144 | thresholdInInterfaces: 11 145 | thresholdInObjects: 11 146 | thresholdInEnums: 11 147 | ignoreDeprecated: false 148 | ignorePrivate: false 149 | ignoreOverridden: false 150 | 151 | coroutines: 152 | active: true 153 | GlobalCoroutineUsage: 154 | active: false 155 | RedundantSuspendModifier: 156 | active: false 157 | SleepInsteadOfDelay: 158 | active: false 159 | SuspendFunWithFlowReturnType: 160 | active: false 161 | 162 | empty-blocks: 163 | active: true 164 | EmptyCatchBlock: 165 | active: true 166 | allowedExceptionNameRegex: '_|(ignore|expected).*' 167 | EmptyClassBlock: 168 | active: true 169 | EmptyDefaultConstructor: 170 | active: true 171 | EmptyDoWhileBlock: 172 | active: true 173 | EmptyElseBlock: 174 | active: true 175 | EmptyFinallyBlock: 176 | active: true 177 | EmptyForBlock: 178 | active: true 179 | EmptyFunctionBlock: 180 | active: true 181 | ignoreOverridden: false 182 | EmptyIfBlock: 183 | active: true 184 | EmptyInitBlock: 185 | active: true 186 | EmptyKtFile: 187 | active: true 188 | EmptySecondaryConstructor: 189 | active: true 190 | EmptyTryBlock: 191 | active: true 192 | EmptyWhenBlock: 193 | active: true 194 | EmptyWhileBlock: 195 | active: true 196 | 197 | exceptions: 198 | active: true 199 | ExceptionRaisedInUnexpectedLocation: 200 | active: true 201 | methodNames: 202 | - 'equals' 203 | - 'finalize' 204 | - 'hashCode' 205 | - 'toString' 206 | InstanceOfCheckForException: 207 | active: false 208 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 209 | NotImplementedDeclaration: 210 | active: false 211 | ObjectExtendsThrowable: 212 | active: false 213 | PrintStackTrace: 214 | active: true 215 | RethrowCaughtException: 216 | active: true 217 | ReturnFromFinally: 218 | active: true 219 | ignoreLabeled: false 220 | SwallowedException: 221 | active: true 222 | ignoredExceptionTypes: 223 | - 'InterruptedException' 224 | - 'MalformedURLException' 225 | - 'NumberFormatException' 226 | - 'ParseException' 227 | allowedExceptionNameRegex: '_|(ignore|expected).*' 228 | ThrowingExceptionFromFinally: 229 | active: true 230 | ThrowingExceptionInMain: 231 | active: false 232 | ThrowingExceptionsWithoutMessageOrCause: 233 | active: true 234 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 235 | exceptions: 236 | - 'ArrayIndexOutOfBoundsException' 237 | - 'Exception' 238 | - 'IllegalArgumentException' 239 | - 'IllegalMonitorStateException' 240 | - 'IllegalStateException' 241 | - 'IndexOutOfBoundsException' 242 | - 'NullPointerException' 243 | - 'RuntimeException' 244 | - 'Throwable' 245 | ThrowingNewInstanceOfSameException: 246 | active: true 247 | TooGenericExceptionCaught: 248 | active: true 249 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 250 | exceptionNames: 251 | - 'ArrayIndexOutOfBoundsException' 252 | - 'Error' 253 | - 'Exception' 254 | - 'IllegalMonitorStateException' 255 | - 'IndexOutOfBoundsException' 256 | - 'NullPointerException' 257 | - 'RuntimeException' 258 | - 'Throwable' 259 | allowedExceptionNameRegex: '_|(ignore|expected).*' 260 | TooGenericExceptionThrown: 261 | active: true 262 | exceptionNames: 263 | - 'Error' 264 | - 'Exception' 265 | - 'RuntimeException' 266 | - 'Throwable' 267 | 268 | formatting: 269 | active: true 270 | android: false 271 | autoCorrect: true 272 | AnnotationOnSeparateLine: 273 | active: false 274 | autoCorrect: true 275 | AnnotationSpacing: 276 | active: false 277 | autoCorrect: true 278 | ArgumentListWrapping: 279 | active: false 280 | autoCorrect: true 281 | indentSize: 4 282 | maxLineLength: 120 283 | ChainWrapping: 284 | active: true 285 | autoCorrect: true 286 | CommentSpacing: 287 | active: true 288 | autoCorrect: true 289 | EnumEntryNameCase: 290 | active: false 291 | autoCorrect: true 292 | Filename: 293 | active: true 294 | FinalNewline: 295 | active: true 296 | autoCorrect: true 297 | insertFinalNewLine: true 298 | ImportOrdering: 299 | active: false 300 | autoCorrect: true 301 | layout: '*,java.**,javax.**,kotlin.**,^' 302 | Indentation: 303 | active: false 304 | autoCorrect: true 305 | indentSize: 4 306 | continuationIndentSize: 4 307 | MaximumLineLength: 308 | active: true 309 | maxLineLength: 120 310 | ignoreBackTickedIdentifier: false 311 | ModifierOrdering: 312 | active: true 313 | autoCorrect: true 314 | MultiLineIfElse: 315 | active: true 316 | autoCorrect: true 317 | NoBlankLineBeforeRbrace: 318 | active: true 319 | autoCorrect: true 320 | NoConsecutiveBlankLines: 321 | active: true 322 | autoCorrect: true 323 | NoEmptyClassBody: 324 | active: true 325 | autoCorrect: true 326 | NoEmptyFirstLineInMethodBlock: 327 | active: false 328 | autoCorrect: true 329 | NoLineBreakAfterElse: 330 | active: true 331 | autoCorrect: true 332 | NoLineBreakBeforeAssignment: 333 | active: true 334 | autoCorrect: true 335 | NoMultipleSpaces: 336 | active: true 337 | autoCorrect: true 338 | NoSemicolons: 339 | active: true 340 | autoCorrect: true 341 | NoTrailingSpaces: 342 | active: true 343 | autoCorrect: true 344 | NoUnitReturn: 345 | active: true 346 | autoCorrect: true 347 | NoUnusedImports: 348 | active: true 349 | autoCorrect: true 350 | NoWildcardImports: 351 | active: true 352 | PackageName: 353 | active: true 354 | autoCorrect: true 355 | ParameterListWrapping: 356 | active: true 357 | autoCorrect: true 358 | indentSize: 4 359 | maxLineLength: 120 360 | SpacingAroundAngleBrackets: 361 | active: false 362 | autoCorrect: true 363 | SpacingAroundColon: 364 | active: true 365 | autoCorrect: true 366 | SpacingAroundComma: 367 | active: true 368 | autoCorrect: true 369 | SpacingAroundCurly: 370 | active: true 371 | autoCorrect: true 372 | SpacingAroundDot: 373 | active: true 374 | autoCorrect: true 375 | SpacingAroundDoubleColon: 376 | active: false 377 | autoCorrect: true 378 | SpacingAroundKeyword: 379 | active: true 380 | autoCorrect: true 381 | SpacingAroundOperators: 382 | active: true 383 | autoCorrect: true 384 | SpacingAroundParens: 385 | active: true 386 | autoCorrect: true 387 | SpacingAroundRangeOperator: 388 | active: true 389 | autoCorrect: true 390 | SpacingAroundUnaryOperator: 391 | active: false 392 | autoCorrect: true 393 | SpacingBetweenDeclarationsWithAnnotations: 394 | active: false 395 | autoCorrect: true 396 | SpacingBetweenDeclarationsWithComments: 397 | active: false 398 | autoCorrect: true 399 | StringTemplate: 400 | active: true 401 | autoCorrect: true 402 | 403 | naming: 404 | active: true 405 | BooleanPropertyNaming: 406 | active: false 407 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 408 | allowedPattern: '^(is|has|are)' 409 | ClassNaming: 410 | active: true 411 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 412 | classPattern: '[A-Z][a-zA-Z0-9]*' 413 | ConstructorParameterNaming: 414 | active: true 415 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 416 | parameterPattern: '[a-z][A-Za-z0-9]*' 417 | privateParameterPattern: '[a-z][A-Za-z0-9]*' 418 | excludeClassPattern: '$^' 419 | ignoreOverridden: true 420 | EnumNaming: 421 | active: true 422 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 423 | enumEntryPattern: '[A-Z][_a-zA-Z0-9]*' 424 | ForbiddenClassName: 425 | active: false 426 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 427 | forbiddenName: [] 428 | FunctionMaxLength: 429 | active: false 430 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 431 | maximumFunctionNameLength: 30 432 | FunctionMinLength: 433 | active: false 434 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 435 | minimumFunctionNameLength: 3 436 | FunctionNaming: 437 | active: true 438 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 439 | functionPattern: '([a-z][a-zA-Z0-9]*)|(`.*`)' 440 | excludeClassPattern: '$^' 441 | ignoreOverridden: true 442 | FunctionParameterNaming: 443 | active: true 444 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 445 | parameterPattern: '[a-z][A-Za-z0-9]*' 446 | excludeClassPattern: '$^' 447 | ignoreOverridden: true 448 | InvalidPackageDeclaration: 449 | active: false 450 | excludes: ['**/*.kts'] 451 | rootPackage: '' 452 | MatchingDeclarationName: 453 | active: true 454 | mustBeFirst: true 455 | MemberNameEqualsClassName: 456 | active: true 457 | ignoreOverridden: true 458 | NoNameShadowing: 459 | active: false 460 | NonBooleanPropertyPrefixedWithIs: 461 | active: false 462 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 463 | ObjectPropertyNaming: 464 | active: true 465 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 466 | constantPattern: '[A-Za-z][_A-Za-z0-9]*' 467 | propertyPattern: '[A-Za-z][_A-Za-z0-9]*' 468 | privatePropertyPattern: '(_)?[A-Za-z][_A-Za-z0-9]*' 469 | PackageNaming: 470 | active: true 471 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 472 | packagePattern: '[a-z]+(\.[a-z][A-Za-z0-9]*)*' 473 | TopLevelPropertyNaming: 474 | active: true 475 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 476 | constantPattern: '[A-Z][_A-Z0-9]*' 477 | propertyPattern: '[A-Za-z][_A-Za-z0-9]*' 478 | privatePropertyPattern: '_?[A-Za-z][_A-Za-z0-9]*' 479 | VariableMaxLength: 480 | active: false 481 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 482 | maximumVariableNameLength: 64 483 | VariableMinLength: 484 | active: false 485 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 486 | minimumVariableNameLength: 1 487 | VariableNaming: 488 | active: true 489 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 490 | variablePattern: '[a-z][A-Za-z0-9]*' 491 | privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*' 492 | excludeClassPattern: '$^' 493 | ignoreOverridden: true 494 | 495 | performance: 496 | active: true 497 | ArrayPrimitive: 498 | active: true 499 | ForEachOnRange: 500 | active: true 501 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 502 | SpreadOperator: 503 | active: true 504 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 505 | UnnecessaryTemporaryInstantiation: 506 | active: true 507 | 508 | potential-bugs: 509 | active: true 510 | AvoidReferentialEquality: 511 | active: false 512 | forbiddenTypePatterns: 513 | - 'kotlin.String' 514 | CastToNullableType: 515 | active: false 516 | Deprecation: 517 | active: false 518 | DontDowncastCollectionTypes: 519 | active: false 520 | DoubleMutabilityForCollection: 521 | active: false 522 | DuplicateCaseInWhenExpression: 523 | active: true 524 | EqualsAlwaysReturnsTrueOrFalse: 525 | active: true 526 | EqualsWithHashCodeExist: 527 | active: true 528 | ExitOutsideMain: 529 | active: false 530 | ExplicitGarbageCollectionCall: 531 | active: true 532 | HasPlatformType: 533 | active: false 534 | IgnoredReturnValue: 535 | active: false 536 | restrictToAnnotatedMethods: true 537 | returnValueAnnotations: 538 | - '*.CheckResult' 539 | - '*.CheckReturnValue' 540 | ignoreReturnValueAnnotations: 541 | - '*.CanIgnoreReturnValue' 542 | ImplicitDefaultLocale: 543 | active: true 544 | ImplicitUnitReturnType: 545 | active: false 546 | allowExplicitReturnType: true 547 | InvalidRange: 548 | active: true 549 | IteratorHasNextCallsNextMethod: 550 | active: true 551 | IteratorNotThrowingNoSuchElementException: 552 | active: true 553 | LateinitUsage: 554 | active: false 555 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 556 | ignoreOnClassesPattern: '' 557 | MapGetWithNotNullAssertionOperator: 558 | active: false 559 | MissingWhenCase: 560 | active: true 561 | allowElseExpression: true 562 | NullableToStringCall: 563 | active: false 564 | RedundantElseInWhen: 565 | active: true 566 | UnconditionalJumpStatementInLoop: 567 | active: false 568 | UnnecessaryNotNullOperator: 569 | active: true 570 | UnnecessarySafeCall: 571 | active: true 572 | UnreachableCatchBlock: 573 | active: false 574 | UnreachableCode: 575 | active: true 576 | UnsafeCallOnNullableType: 577 | active: true 578 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 579 | UnsafeCast: 580 | active: true 581 | UnusedUnaryOperator: 582 | active: false 583 | UselessPostfixExpression: 584 | active: false 585 | WrongEqualsTypeParameter: 586 | active: true 587 | 588 | style: 589 | active: true 590 | ClassOrdering: 591 | active: false 592 | CollapsibleIfStatements: 593 | active: false 594 | DataClassContainsFunctions: 595 | active: false 596 | conversionFunctionPrefix: 'to' 597 | DataClassShouldBeImmutable: 598 | active: false 599 | DestructuringDeclarationWithTooManyEntries: 600 | active: false 601 | maxDestructuringEntries: 3 602 | EqualsNullCall: 603 | active: true 604 | EqualsOnSignatureLine: 605 | active: false 606 | ExplicitCollectionElementAccessMethod: 607 | active: false 608 | ExplicitItLambdaParameter: 609 | active: false 610 | ExpressionBodySyntax: 611 | active: false 612 | includeLineWrapping: false 613 | ForbiddenComment: 614 | active: true 615 | values: 616 | - 'FIXME:' 617 | - 'STOPSHIP:' 618 | - 'TODO:' 619 | allowedPatterns: '' 620 | ForbiddenImport: 621 | active: false 622 | imports: [] 623 | forbiddenPatterns: '' 624 | ForbiddenMethodCall: 625 | active: false 626 | methods: 627 | - 'kotlin.io.print' 628 | - 'kotlin.io.println' 629 | ForbiddenPublicDataClass: 630 | active: true 631 | excludes: ['**'] 632 | ignorePackages: 633 | - '*.internal' 634 | - '*.internal.*' 635 | ForbiddenVoid: 636 | active: false 637 | ignoreOverridden: false 638 | ignoreUsageInGenerics: false 639 | FunctionOnlyReturningConstant: 640 | active: true 641 | ignoreOverridableFunction: true 642 | ignoreActualFunction: true 643 | excludedFunctions: '' 644 | LibraryCodeMustSpecifyReturnType: 645 | active: true 646 | excludes: ['**'] 647 | LibraryEntitiesShouldNotBePublic: 648 | active: true 649 | excludes: ['**'] 650 | LoopWithTooManyJumpStatements: 651 | active: true 652 | maxJumpCount: 1 653 | MagicNumber: 654 | active: true 655 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 656 | ignoreNumbers: 657 | - '-1' 658 | - '0' 659 | - '1' 660 | - '2' 661 | ignoreHashCodeFunction: true 662 | ignorePropertyDeclaration: false 663 | ignoreLocalVariableDeclaration: false 664 | ignoreConstantDeclaration: true 665 | ignoreCompanionObjectPropertyDeclaration: true 666 | ignoreAnnotation: false 667 | ignoreNamedArgument: true 668 | ignoreEnums: false 669 | ignoreRanges: false 670 | ignoreExtensionFunctions: true 671 | MandatoryBracesIfStatements: 672 | active: false 673 | MandatoryBracesLoops: 674 | active: false 675 | MaxLineLength: 676 | active: true 677 | maxLineLength: 120 678 | excludePackageStatements: true 679 | excludeImportStatements: true 680 | excludeCommentStatements: false 681 | MayBeConst: 682 | active: true 683 | ModifierOrder: 684 | active: true 685 | MultilineLambdaItParameter: 686 | active: false 687 | NestedClassesVisibility: 688 | active: true 689 | NewLineAtEndOfFile: 690 | active: true 691 | NoTabs: 692 | active: false 693 | ObjectLiteralToLambda: 694 | active: false 695 | OptionalAbstractKeyword: 696 | active: true 697 | OptionalUnit: 698 | active: false 699 | OptionalWhenBraces: 700 | active: false 701 | PreferToOverPairSyntax: 702 | active: false 703 | ProtectedMemberInFinalClass: 704 | active: true 705 | RedundantExplicitType: 706 | active: false 707 | RedundantHigherOrderMapUsage: 708 | active: false 709 | RedundantVisibilityModifierRule: 710 | active: false 711 | ReturnCount: 712 | active: true 713 | max: 2 714 | excludedFunctions: 'equals' 715 | excludeLabeled: false 716 | excludeReturnFromLambda: true 717 | excludeGuardClauses: false 718 | SafeCast: 719 | active: true 720 | SerialVersionUIDInSerializableClass: 721 | active: true 722 | SpacingBetweenPackageAndImports: 723 | active: false 724 | ThrowsCount: 725 | active: true 726 | max: 2 727 | excludeGuardClauses: false 728 | TrailingWhitespace: 729 | active: false 730 | # UnderscoresInNumericLiterals: 731 | # active: false 732 | # acceptableLength: 4 733 | UnnecessaryAbstractClass: 734 | active: true 735 | UnnecessaryAnnotationUseSiteTarget: 736 | active: false 737 | UnnecessaryApply: 738 | active: true 739 | UnnecessaryFilter: 740 | active: false 741 | UnnecessaryInheritance: 742 | active: true 743 | UnnecessaryLet: 744 | active: false 745 | UnnecessaryParentheses: 746 | active: false 747 | UntilInsteadOfRangeTo: 748 | active: false 749 | UnusedImports: 750 | active: false 751 | UnusedPrivateClass: 752 | active: true 753 | UnusedPrivateMember: 754 | active: true 755 | allowedNames: '(_|ignored|expected|serialVersionUID)' 756 | UseArrayLiteralsInAnnotations: 757 | active: false 758 | UseCheckNotNull: 759 | active: false 760 | UseCheckOrError: 761 | active: false 762 | UseDataClass: 763 | active: false 764 | allowVars: false 765 | UseEmptyCounterpart: 766 | active: false 767 | UseIfEmptyOrIfBlank: 768 | active: false 769 | UseIfInsteadOfWhen: 770 | active: false 771 | UseIsNullOrEmpty: 772 | active: false 773 | UseOrEmpty: 774 | active: false 775 | UseRequire: 776 | active: false 777 | UseRequireNotNull: 778 | active: false 779 | UselessCallOnNotNull: 780 | active: true 781 | UtilityClassWithPublicConstructor: 782 | active: true 783 | VarCouldBeVal: 784 | active: true 785 | WildcardImport: 786 | active: true 787 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] 788 | excludeImports: 789 | - 'java.util.*' 790 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @xmartlabs/android-open-source -------------------------------------------------------------------------------- /.github/workflows/compile-and-check.yml: -------------------------------------------------------------------------------- 1 | name: Run lints and build 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - main 7 | jobs: 8 | detekt_and_build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: Cache files 13 | uses: actions/cache@v2 14 | with: 15 | path: | 16 | ~/.gradle/caches 17 | ~/.gradle/wrapper 18 | ~/.android/build-cache 19 | key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}-${{ hashFiles('**/gradle-wrapper.properties') }} 20 | restore-keys: | 21 | ${{ runner.os }}-gradle- 22 | - name: Gradle Initialization 23 | run: ./gradlew 24 | - name: Detekt 25 | run: ./gradlew detekt 26 | - name: Upload Detekt report 27 | uses: actions/upload-artifact@v2 28 | if: failure() 29 | with: 30 | name: Detekt report 31 | path: build/reports/detekt/detekt.html 32 | - name: Build 33 | run: ./gradlew :typednavigation:build 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | TypedNavigation -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 126 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TypedNavigation 2 | 3 | [![Run detekt and build](https://github.com/xmartlabs/TypedNavigation/actions/workflows/compile-and-check.yml/badge.svg)](https://github.com/xmartlabs/TypedNavigation/actions/workflows/compile-and-check.yml) 4 | [![](https://jitpack.io/v/xmartlabs/TypedNavigation.svg)](https://jitpack.io/#xmartlabs/TypedNavigation) 5 | 6 | A lightweight library to help you navigate in compose with well typed functions. 7 | 8 | ## Installation: 9 | 10 | You can add this library to your project by just adding the following code to your root `build.gradle` 11 | 12 | ```groovy 13 | allprojects { 14 | repositories { 15 | // ... 16 | maven { url 'https://jitpack.io' } 17 | } 18 | } 19 | ``` 20 | 21 | Then import the library in your app `build.gradle` file. 22 | 23 | ```groovy 24 | implementation 'com.github.xmartlabs:TypedNavigation:0.0.4' 25 | ``` 26 | 27 | ## Usage: 28 | 29 | You just have to define your screens and the arguments they receive: 30 | 31 | ```kotlin 32 | object Router { 33 | val default = TypedNavigation.E("default") 34 | val sample = TypedNavigation.A3("sample", NavType.StringType, NavType.StringType, NavType.StringType) 35 | } 36 | ``` 37 | 38 | And after that the library will provide you with the following functions: 39 | 40 | To add your screen to the `NavHost`: 41 | 42 | ```kotlin 43 | setContent { 44 | val navigationController: NavHostController = rememberNavController() 45 | NavHost(navController = navigationController, startDestination = Router.default.url) { 46 | composable(Router.default) { 47 | Default(navigationController = navigationController) 48 | } 49 | composable(Router.example) { a: String?, b: String?, c: String? -> 50 | Example(a, b, c) 51 | } 52 | } 53 | } 54 | ``` 55 | 56 | To navigate from one screen to another: 57 | 58 | ```kotlin 59 | navigationController.navigate(Router.example.route("a", "b", "c")) 60 | ``` 61 | 62 | Add deep linking to your screen by setting up the correct path to the url: 63 | 64 | ```kotlin 65 | val example = 66 | TypedNavigation.A3("example", NavType.StringType, NavType.StringType, NavType.StringType, 67 | listOf { a1, a2, a3 -> // a1, a2 and a3 contains the keys for the attributes previously defined 68 | "www.example.com/$a1/$a2/$a3" 69 | } 70 | ) 71 | ``` 72 | 73 | ### Use it with hilt ViewModel 74 | You can access attributes stored in the `SavedStateHandle` by using `withAttributes` 75 | 76 | ```kotlin 77 | @HiltViewModel 78 | class HiltExampleViewModel @Inject constructor( 79 | savedStateHandle: SavedStateHandle 80 | ) : ViewModel() { 81 | data class ScreenState(val name: String? = null, val age: Int? = null, val knowsHilt: Boolean? = null) 82 | 83 | val stateFlow: MutableStateFlow = MutableStateFlow(ScreenState()) 84 | 85 | init { 86 | Router.hiltExample.withAttributes(savedStateHandle) { name, age, knowsHilt -> 87 | viewModelScope.launch { 88 | stateFlow.emit(ScreenState(name!!, age, knowsHilt)) 89 | } 90 | } 91 | } 92 | } 93 | ``` 94 | 95 | For more examples you can check out our example app. 96 | 97 | ## About 98 | 99 | Made with ❤️ by [XMARTLABS](http://xmartlabs.com) 100 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'kotlin-android' 4 | id 'kotlin-parcelize' 5 | id 'kotlin-kapt' 6 | id 'dagger.hilt.android.plugin' 7 | } 8 | 9 | android { 10 | compileSdk 31 11 | 12 | defaultConfig { 13 | applicationId "com.xmartlabs.typednavigation" 14 | minSdk 21 15 | targetSdk 31 16 | versionCode 1 17 | versionName "1.0" 18 | 19 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 20 | vectorDrawables { 21 | useSupportLibrary true 22 | } 23 | } 24 | 25 | buildTypes { 26 | release { 27 | minifyEnabled false 28 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 29 | } 30 | } 31 | compileOptions { 32 | sourceCompatibility JavaVersion.VERSION_1_8 33 | targetCompatibility JavaVersion.VERSION_1_8 34 | } 35 | kotlinOptions { 36 | jvmTarget = '1.8' 37 | useIR = true 38 | languageVersion = "1.5" 39 | } 40 | buildFeatures { 41 | compose true 42 | } 43 | composeOptions { 44 | kotlinCompilerExtensionVersion compose_version 45 | kotlinCompilerVersion '1.5.31' 46 | } 47 | packagingOptions { 48 | resources { 49 | excludes += '/META-INF/{AL2.0,LGPL2.1}' 50 | } 51 | } 52 | } 53 | 54 | dependencies { 55 | 56 | implementation "androidx.compose.material:material:$compose_version" 57 | implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" 58 | implementation "androidx.compose.ui:ui:$compose_version" 59 | implementation "com.google.dagger:hilt-android:2.38.1" 60 | implementation 'androidx.activity:activity-compose:1.4.0' 61 | implementation 'androidx.appcompat:appcompat:1.4.1' 62 | implementation 'androidx.core:core-ktx:1.7.0' 63 | implementation 'androidx.hilt:hilt-navigation-compose:1.0.0-rc01' 64 | implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0' 65 | implementation 'androidx.navigation:navigation-compose:2.4.0-rc01' 66 | implementation 'com.google.android.material:material:1.5.0' 67 | implementation project(":typednavigation") 68 | 69 | kapt "com.google.dagger:hilt-compiler:2.38.1" 70 | 71 | testImplementation 'junit:junit:4.+' 72 | androidTestImplementation 'androidx.test.ext:junit:1.1.3' 73 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 74 | androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" 75 | debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" 76 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/xmartlabs/typednavigation/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.xmartlabs.typednavigation 2 | 3 | import androidx.test.ext.junit.runners.AndroidJUnit4 4 | import androidx.test.platform.app.InstrumentationRegistry 5 | import org.junit.Assert.assertEquals 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | /** 10 | * Instrumented test, which will execute on an Android device. 11 | * 12 | * See [testing documentation](http://d.android.com/tools/testing). 13 | */ 14 | @RunWith(AndroidJUnit4::class) 15 | class ExampleInstrumentedTest { 16 | @Test 17 | fun useAppContext() { 18 | // Context of the app under test. 19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 20 | assertEquals("com.xmartlabs.typednavigation", appContext.packageName) 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/xmartlabs/typednavigation/App.kt: -------------------------------------------------------------------------------- 1 | package com.xmartlabs.typednavigation 2 | 3 | import android.app.Application 4 | import dagger.hilt.android.HiltAndroidApp 5 | 6 | @HiltAndroidApp 7 | class App : Application() { 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/xmartlabs/typednavigation/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.xmartlabs.typednavigation 2 | 3 | import android.os.Bundle 4 | import androidx.activity.compose.setContent 5 | import androidx.appcompat.app.AppCompatActivity 6 | import androidx.compose.foundation.layout.Arrangement 7 | import androidx.compose.foundation.layout.Box 8 | import androidx.compose.foundation.layout.Row 9 | import androidx.compose.foundation.layout.fillMaxSize 10 | import androidx.compose.foundation.layout.padding 11 | import androidx.compose.material.Button 12 | import androidx.compose.material.Text 13 | import androidx.compose.runtime.Composable 14 | import androidx.compose.ui.Alignment 15 | import androidx.compose.ui.Modifier 16 | import androidx.compose.ui.unit.dp 17 | import androidx.hilt.navigation.compose.hiltViewModel 18 | import androidx.navigation.NavHostController 19 | import androidx.navigation.NavType 20 | import androidx.navigation.compose.NavHost 21 | import androidx.navigation.compose.rememberNavController 22 | import com.xmartlabs.typednavigation.ui.hiltExapmle.HiltExample 23 | import com.xmartlabs.typednavigation.ui.hiltExapmle.HiltExampleViewModel 24 | import com.xmartlabs.typednavigation.ui.theme.TypedNavigationTheme 25 | import dagger.hilt.android.AndroidEntryPoint 26 | 27 | @AndroidEntryPoint 28 | class MainActivity : AppCompatActivity() { 29 | override fun onCreate(savedInstanceState: Bundle?) { 30 | super.onCreate(savedInstanceState) 31 | setContent { 32 | val navigationController: NavHostController = rememberNavController() 33 | NavHost(navController = navigationController, startDestination = Router.default.url) { 34 | composable(Router.default) { 35 | Default(navigationController = navigationController) 36 | } 37 | composable(Router.home) { a1, a2 -> 38 | Home(a1, a2) 39 | } 40 | composable(Router.example) { a, b, c -> 41 | Example(a, b, c) 42 | } 43 | composable(Router.hiltExample) { 44 | val hiltExampleViewModel = hiltViewModel() 45 | HiltExample(hiltExampleViewModel) 46 | } 47 | } 48 | } 49 | } 50 | } 51 | 52 | @Composable 53 | fun Default(navigationController: NavHostController) = Box( 54 | contentAlignment = Alignment.Center, 55 | modifier = Modifier.fillMaxSize() 56 | ) { 57 | Row( 58 | verticalAlignment = Alignment.CenterVertically, 59 | horizontalArrangement = Arrangement.SpaceEvenly 60 | ) { 61 | Button( 62 | onClick = { navigationController.navigate(Router.home.route("example", 5)) }, 63 | modifier = Modifier.padding(end = 10.dp) 64 | ) { 65 | Text(text = "Home") 66 | } 67 | Button( 68 | onClick = { navigationController.navigate(Router.example.route("a", "b", "c")) }, 69 | modifier = Modifier.padding(end = 10.dp) 70 | ) { 71 | Text(text = "Example") 72 | } 73 | Button(onClick = { navigationController.navigate(Router.hiltExample.route(null, null, false)) }) { 74 | Text(text = "Hilt Example") 75 | } 76 | } 77 | } 78 | 79 | @Composable 80 | fun Home(a1: String?, a2: Int) = Box( 81 | contentAlignment = Alignment.Center, 82 | modifier = Modifier.fillMaxSize() 83 | ) { 84 | Text(text = "Hello $a1 $a2!") 85 | } 86 | 87 | @Composable 88 | fun Example(a1: String?, a2: String?, a3: String?) = Box( 89 | contentAlignment = Alignment.Center, 90 | modifier = Modifier.fillMaxSize() 91 | ) { 92 | TypedNavigationTheme { 93 | Text(text = "Hello $a1 $a2 $a3!") 94 | } 95 | } 96 | 97 | object Router { 98 | val default = TypedNavigation.E("default") 99 | val home = TypedNavigation.A2("home", NavType.StringType, NavType.IntType) 100 | val example = 101 | TypedNavigation.A3("example", NavType.StringType, NavType.StringType, NavType.StringType, listOf { a1, a2, a3 -> 102 | "www.example.com/$a1/$a2/$a3" 103 | } 104 | ) 105 | val hiltExample = 106 | TypedNavigation.A3("hiltExample", NavType.StringType, NavType.NullableBool, NavType.BoolType) 107 | } 108 | -------------------------------------------------------------------------------- /app/src/main/java/com/xmartlabs/typednavigation/ui/hiltExapmle/HiltExample.kt: -------------------------------------------------------------------------------- 1 | package com.xmartlabs.typednavigation.ui.hiltExapmle 2 | 3 | import androidx.compose.material.Text 4 | import androidx.compose.runtime.Composable 5 | import androidx.compose.runtime.collectAsState 6 | import androidx.compose.runtime.getValue 7 | import androidx.lifecycle.viewmodel.compose.viewModel 8 | 9 | @Composable 10 | fun HiltExample( 11 | viewModel: HiltExampleViewModel 12 | ) { 13 | val state by viewModel.stateFlow.collectAsState() 14 | Text(text = "Hello ${state.name} your age is ${state.age} and you ${if (state.knowsHilt == true) "know" else "don't know"} hilt") 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/xmartlabs/typednavigation/ui/hiltExapmle/HiltExampleViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.xmartlabs.typednavigation.ui.hiltExapmle 2 | 3 | import androidx.lifecycle.SavedStateHandle 4 | import androidx.lifecycle.ViewModel 5 | import androidx.lifecycle.viewModelScope 6 | import com.xmartlabs.typednavigation.Router 7 | import com.xmartlabs.typednavigation.withAttributes 8 | import dagger.hilt.android.lifecycle.HiltViewModel 9 | import kotlinx.coroutines.flow.MutableStateFlow 10 | import kotlinx.coroutines.launch 11 | import javax.inject.Inject 12 | 13 | @HiltViewModel 14 | class HiltExampleViewModel @Inject constructor( 15 | savedStateHandle: SavedStateHandle 16 | ) : ViewModel() { 17 | data class ScreenState(val name: String? = null, val age: Boolean? = null, val knowsHilt: Boolean? = null) 18 | 19 | val stateFlow: MutableStateFlow = MutableStateFlow(ScreenState()) 20 | 21 | init { 22 | Router.hiltExample.withAttributes(savedStateHandle) { name, age, knowsHilt -> 23 | viewModelScope.launch { 24 | stateFlow.emit(ScreenState(name!!, age, knowsHilt)) 25 | } 26 | } 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/xmartlabs/typednavigation/ui/theme/Color.kt: -------------------------------------------------------------------------------- 1 | package com.xmartlabs.typednavigation.ui.theme 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | val Purple200 = Color(0xFFBB86FC) 6 | val Purple500 = Color(0xFF6200EE) 7 | val Purple700 = Color(0xFF3700B3) 8 | val Teal200 = Color(0xFF03DAC5) -------------------------------------------------------------------------------- /app/src/main/java/com/xmartlabs/typednavigation/ui/theme/Shape.kt: -------------------------------------------------------------------------------- 1 | package com.xmartlabs.typednavigation.ui.theme 2 | 3 | import androidx.compose.foundation.shape.RoundedCornerShape 4 | import androidx.compose.material.Shapes 5 | import androidx.compose.ui.unit.dp 6 | 7 | val Shapes = Shapes( 8 | small = RoundedCornerShape(4.dp), 9 | medium = RoundedCornerShape(4.dp), 10 | large = RoundedCornerShape(0.dp) 11 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/xmartlabs/typednavigation/ui/theme/Theme.kt: -------------------------------------------------------------------------------- 1 | package com.xmartlabs.typednavigation.ui.theme 2 | 3 | import androidx.compose.foundation.isSystemInDarkTheme 4 | import androidx.compose.material.MaterialTheme 5 | import androidx.compose.material.darkColors 6 | import androidx.compose.material.lightColors 7 | import androidx.compose.runtime.Composable 8 | 9 | private val DarkColorPalette = darkColors( 10 | primary = Purple200, 11 | primaryVariant = Purple700, 12 | secondary = Teal200 13 | ) 14 | 15 | private val LightColorPalette = lightColors( 16 | primary = Purple500, 17 | primaryVariant = Purple700, 18 | secondary = Teal200 19 | 20 | /* Other default colors to override 21 | background = Color.White, 22 | surface = Color.White, 23 | onPrimary = Color.White, 24 | onSecondary = Color.Black, 25 | onBackground = Color.Black, 26 | onSurface = Color.Black, 27 | */ 28 | ) 29 | 30 | @Composable 31 | fun TypedNavigationTheme( 32 | darkTheme: Boolean = isSystemInDarkTheme(), 33 | content: @Composable() () -> Unit 34 | ) { 35 | val colors = if (darkTheme) { 36 | DarkColorPalette 37 | } else { 38 | LightColorPalette 39 | } 40 | 41 | MaterialTheme( 42 | colors = colors, 43 | typography = Typography, 44 | shapes = Shapes, 45 | content = content 46 | ) 47 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xmartlabs/typednavigation/ui/theme/Type.kt: -------------------------------------------------------------------------------- 1 | package com.xmartlabs.typednavigation.ui.theme 2 | 3 | import androidx.compose.material.Typography 4 | import androidx.compose.ui.text.TextStyle 5 | import androidx.compose.ui.text.font.FontFamily 6 | import androidx.compose.ui.text.font.FontWeight 7 | import androidx.compose.ui.unit.sp 8 | 9 | // Set of Material typography styles to start with 10 | val Typography = Typography( 11 | body1 = TextStyle( 12 | fontFamily = FontFamily.Default, 13 | fontWeight = FontWeight.Normal, 14 | fontSize = 16.sp 15 | ) 16 | /* Other default text styles to override 17 | button = TextStyle( 18 | fontFamily = FontFamily.Default, 19 | fontWeight = FontWeight.W500, 20 | fontSize = 14.sp 21 | ), 22 | caption = TextStyle( 23 | fontFamily = FontFamily.Default, 24 | fontWeight = FontWeight.Normal, 25 | fontSize = 12.sp 26 | ) 27 | */ 28 | ) -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmartlabs/TypedNavigation/cafc9db817cdf773a5a3b89058532eb2605cba8f/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmartlabs/TypedNavigation/cafc9db817cdf773a5a3b89058532eb2605cba8f/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmartlabs/TypedNavigation/cafc9db817cdf773a5a3b89058532eb2605cba8f/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmartlabs/TypedNavigation/cafc9db817cdf773a5a3b89058532eb2605cba8f/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmartlabs/TypedNavigation/cafc9db817cdf773a5a3b89058532eb2605cba8f/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmartlabs/TypedNavigation/cafc9db817cdf773a5a3b89058532eb2605cba8f/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmartlabs/TypedNavigation/cafc9db817cdf773a5a3b89058532eb2605cba8f/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmartlabs/TypedNavigation/cafc9db817cdf773a5a3b89058532eb2605cba8f/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmartlabs/TypedNavigation/cafc9db817cdf773a5a3b89058532eb2605cba8f/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmartlabs/TypedNavigation/cafc9db817cdf773a5a3b89058532eb2605cba8f/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | TypedNavigation 3 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | 17 | 21 | 22 |