Change app theme (#330)

This commit is contained in:
Rafał Borcz 2019-08-26 20:54:20 +02:00 committed by Mikołaj Pich
parent b0033af048
commit c6d9dfa0c9
231 changed files with 2225 additions and 1511 deletions

View File

@ -1,9 +1,6 @@
<component name="ProjectCodeStyleConfiguration"> <component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173"> <code_scheme name="Project" version="173">
<option name="LINE_SEPARATOR" value="&#10;" /> <option name="LINE_SEPARATOR" value="&#10;" />
<AndroidXmlCodeStyleSettings>
<option name="USE_CUSTOM_SETTINGS" value="true" />
</AndroidXmlCodeStyleSettings>
<JetCodeStyleSettings> <JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS"> <option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value> <value>
@ -24,13 +21,7 @@
<MarkdownNavigatorCodeStyleSettings> <MarkdownNavigatorCodeStyleSettings>
<option name="RIGHT_MARGIN" value="72" /> <option name="RIGHT_MARGIN" value="72" />
</MarkdownNavigatorCodeStyleSettings> </MarkdownNavigatorCodeStyleSettings>
<XML>
<option name="XML_KEEP_LINE_BREAKS" value="false" />
<option name="XML_ALIGN_ATTRIBUTES" value="false" />
<option name="XML_SPACE_INSIDE_EMPTY_TAG" value="true" />
</XML>
<codeStyleSettings language="XML"> <codeStyleSettings language="XML">
<option name="FORCE_REARRANGE_MODE" value="1" />
<indentOptions> <indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" /> <option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions> </indentOptions>
@ -41,6 +32,7 @@
<match> <match>
<AND> <AND>
<NAME>xmlns:android</NAME> <NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE> <XML_NAMESPACE>^$</XML_NAMESPACE>
</AND> </AND>
</match> </match>
@ -51,6 +43,7 @@
<match> <match>
<AND> <AND>
<NAME>xmlns:.*</NAME> <NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE> <XML_NAMESPACE>^$</XML_NAMESPACE>
</AND> </AND>
</match> </match>
@ -62,6 +55,7 @@
<match> <match>
<AND> <AND>
<NAME>.*:id</NAME> <NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND> </AND>
</match> </match>
@ -72,6 +66,7 @@
<match> <match>
<AND> <AND>
<NAME>.*:name</NAME> <NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND> </AND>
</match> </match>
@ -82,6 +77,7 @@
<match> <match>
<AND> <AND>
<NAME>name</NAME> <NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE> <XML_NAMESPACE>^$</XML_NAMESPACE>
</AND> </AND>
</match> </match>
@ -92,6 +88,7 @@
<match> <match>
<AND> <AND>
<NAME>style</NAME> <NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE> <XML_NAMESPACE>^$</XML_NAMESPACE>
</AND> </AND>
</match> </match>
@ -102,6 +99,7 @@
<match> <match>
<AND> <AND>
<NAME>.*</NAME> <NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE> <XML_NAMESPACE>^$</XML_NAMESPACE>
</AND> </AND>
</match> </match>
@ -113,6 +111,7 @@
<match> <match>
<AND> <AND>
<NAME>.*</NAME> <NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND> </AND>
</match> </match>
@ -124,6 +123,7 @@
<match> <match>
<AND> <AND>
<NAME>.*</NAME> <NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE> <XML_NAMESPACE>.*</XML_NAMESPACE>
</AND> </AND>
</match> </match>
@ -141,7 +141,6 @@
<option name="METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" /> <option name="METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
<option name="METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" /> <option name="METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
<option name="EXTENDS_LIST_WRAP" value="1" /> <option name="EXTENDS_LIST_WRAP" value="1" />
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
<indentOptions> <indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" /> <option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions> </indentOptions>

View File

@ -65,6 +65,7 @@ android {
} }
flavorDimensions "platform" flavorDimensions "platform"
productFlavors { productFlavors {
play { play {
dimension "platform" dimension "platform"
@ -84,6 +85,11 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
} }
packagingOptions {
exclude 'META-INF/library_release.kotlin_module'
exclude 'META-INF/library-core_release.kotlin_module'
}
} }
androidExtensions { androidExtensions {
@ -106,6 +112,11 @@ ext {
mockito_core = "3.0.6" mockito_core = "3.0.6"
} }
configurations.all {
resolutionStrategy.force "androidx.constraintlayout:constraintlayout:1.1.3"
resolutionStrategy.force "com.google.android.material:material:1.1.0-alpha07"
}
dependencies { dependencies {
implementation "io.github.wulkanowy:api:0.9.4" implementation "io.github.wulkanowy:api:0.9.4"
@ -116,14 +127,16 @@ dependencies {
implementation "androidx.annotation:annotation:1.1.0" implementation "androidx.annotation:annotation:1.1.0"
implementation "androidx.multidex:multidex:2.0.1" implementation "androidx.multidex:multidex:2.0.1"
implementation "androidx.preference:preference:1.1.0-rc01"
implementation "androidx.recyclerview:recyclerview:1.0.0" implementation "androidx.recyclerview:recyclerview:1.0.0"
implementation "androidx.viewpager:viewpager:1.0.0" implementation "androidx.viewpager:viewpager:1.0.0"
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
implementation "androidx.constraintlayout:constraintlayout:1.1.3" implementation "androidx.constraintlayout:constraintlayout:1.1.3"
implementation "androidx.coordinatorlayout:coordinatorlayout:1.0.0" implementation "androidx.coordinatorlayout:coordinatorlayout:1.0.0"
implementation "com.google.android.material:material:1.1.0-alpha07" implementation "com.google.android.material:material:1.1.0-alpha07"
implementation "com.github.wulkanowy:MaterialChipsInput:b72fd0ee6f" implementation "com.github.wulkanowy:material-chips-input:2.0.1"
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0" implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
implementation "me.zhanghai.android.materialprogressbar:library:1.6.1"
implementation "androidx.work:work-runtime:$work_manager" implementation "androidx.work:work-runtime:$work_manager"
implementation "androidx.work:work-rxjava2:$work_manager" implementation "androidx.work:work-rxjava2:$work_manager"
@ -152,9 +165,7 @@ dependencies {
implementation "com.jakewharton.timber:timber:4.7.1" implementation "com.jakewharton.timber:timber:4.7.1"
implementation "at.favre.lib:slf4j-timber:1.0.1" implementation "at.favre.lib:slf4j-timber:1.0.1"
implementation "com.squareup.okhttp3:logging-interceptor:3.12.3" implementation "com.squareup.okhttp3:logging-interceptor:3.12.3"
implementation "com.mikepenz:aboutlibraries:7.0.2"
implementation "com.mikepenz:aboutlibraries:6.2.3"
implementation "com.takisoft.preferencex:preferencex:1.0.0"
playImplementation "com.google.firebase:firebase-core:17.1.0" playImplementation "com.google.firebase:firebase-core:17.1.0"
playImplementation "com.crashlytics.sdk.android:crashlytics:2.10.1" playImplementation "com.crashlytics.sdk.android:crashlytics:2.10.1"

View File

@ -1,7 +1,7 @@
apply plugin: "jacoco" apply plugin: "jacoco"
jacoco { jacoco {
toolVersion "0.8.3" toolVersion "0.8.4"
reportsDir = file("$buildDir/reports") reportsDir = file("$buildDir/reports")
} }

View File

@ -11,6 +11,10 @@
-verbose -verbose
#Keep all wulkanowy files
-keep class io.github.wulkanowy.** {*;}
#Config for anallitycs #Config for anallitycs
-keepattributes *Annotation* -keepattributes *Annotation*
-keepattributes SourceFile,LineNumberTable -keepattributes SourceFile,LineNumberTable
@ -32,11 +36,10 @@
-dontwarn rx.internal.util.** -dontwarn rx.internal.util.**
-dontwarn sun.misc.Unsafe -dontwarn sun.misc.Unsafe
#Config for MPAndroidChart #Config for MPAndroidChart
-keep class com.github.mikephil.charting.** { *; } -keep class com.github.mikephil.charting.** { *; }
#Config for API
-keep class io.github.wulkanowy.api.** {*;}
#Config for Material Components #Config for Material Components
-keep class com.google.android.material.tabs.** {*;} -keep class com.google.android.material.tabs.**

View File

@ -1,58 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="1926.9231"
android:viewportHeight="1926.9231">
<group android:translateX="462.46155"
android:translateY="462.46155">
<path
android:pathData="M2000,1440.1V2002H1240.1L238.1,1000v0l-120,-120c0.2,-0.2 -0.7,-1.6 -0.6,-1.8 1.6,-3.1 3.4,-6 5,-9.1 0.4,-0.8 0.6,-1.6 0.6,-2.5 9.2,-15.1 20.2,-28.9 31.4,-42.6 0.1,-0.2 0.3,-0.3 0.4,-0.5 5.1,-6.3 10.3,-12.6 15.3,-18.9 1,-1.2 1.9,-2.4 2.9,-3.7 0.2,-0.2 0.3,-0.4 0.5,-0.6 7.6,-9.7 14.8,-19.7 21.2,-30.2 1,-1.7 2,-3.4 2.9,-5.1 0.1,-0.2 0.2,-0.3 0.3,-0.5 6.2,-11.4 11.3,-23.3 17.7,-34.6 4.5,-8 9.3,-15.9 13.8,-23.9 0.1,-0.2 0.2,-0.3 0.3,-0.5 0.8,-1.5 1.6,-3 2.4,-4.4 0.2,-0.3 0.3,-0.6 0.5,-0.9 2,-3.7 3.8,-7.4 5.6,-11.2 6.2,-13.4 10.2,-27.7 14,-41.9 0,-0.2 0.1,-0.3 0.1,-0.5 0.3,-1 0.5,-2 0.8,-2.9 4,-15.3 7.3,-31.4 13.5,-45.9 1.4,-3.3 3,-6.5 4.6,-9.6 0.1,-0.2 0.2,-0.3 0.3,-0.5 5,-9.7 10.6,-19.1 13.5,-29.7 2.6,-9.2 3.5,-19 3.6,-28.8 0,-0.2 0,-0.3 0,-0.5 0.1,-7.2 -0.1,-14.4 -0.4,-21.3 0.9,-5.6 1.9,-11.3 3,-16.9 0.2,-0.9 0.3,-1.7 0.5,-2.6 1.2,-5.9 2.5,-11.7 4.2,-17.4 0,-0.1 0.1,-0.3 0.1,-0.4 0,-0.2 0.1,-0.3 0.1,-0.5 0.2,-2.1 -0.8,-3.7 -2.4,-4.5l7.7,-7.6c1.2,0.9 2.7,1.3 4.3,0.9 12.8,-3.9 24.9,-9.9 36.3,-16.8 2.8,-1.7 5.6,-3.4 8.3,-5.2 0.2,-0.1 0.3,-0.2 0.5,-0.3 7.7,-4.9 15.2,-10.2 22.1,-16 3.1,-2.7 5.9,-5.6 8.3,-8.9 0.1,-0.2 0.2,-0.3 0.4,-0.5 2.3,-3.4 4.2,-7.2 5.3,-11.4 2.4,-9.2 1.9,-19 1.9,-28.4 0,-0.2 0,-0.4 0,-0.6l5.7,-5.6 -0.3,0.1 4.1,1.3 45.3,45 9.6,9.6 14.3,14.3 100.8,100.8 17.2,17.2 16.3,16.3 30.3,-30.3 -192.9,-191.5c0.5,-0.5 1.1,-1.6 1.4,-2.3 0.3,-0.6 0.5,-1.2 0.4,-1.9 0,-0.8 -0.2,-1.6 -0.6,-2.3 -0.1,-0.3 -0.3,-0.7 -0.4,-1 -0.2,-0.4 -0.5,-0.7 -0.9,-1.1l27.8,-27.8 191.1,-191.1c0.7,0.4 1.5,0.6 2.5,0.7 4.1,0 8.2,0.1 11.9,1.9 0.5,0.3 1.3,0.7 2.1,1.1 1.7,2.3 3.5,4.5 5.7,6.2 2.7,2.1 8.2,3 9.4,0.3z"
android:fillColor="#AD2A2A"/>
<path
android:pathData="m616.3,796.7c0.4,1.2 0.5,2.4 0.5,3.7l-5.8,73.3c-0.4,5.2 -5,9.3 -10.6,9.3h-187.2c-4,0 -7.7,-2.3 -9.5,-5.6l-30.9,-57.4c-0.2,-0.3 -0.3,-0.6 -0.4,-0.9l-29.1,-70.5c-1.1,-2.5 -0.9,-5.4 0.3,-7.8l48.3,-94.5c1.2,-2.3 1.4,-5 0.5,-7.4l-23.6,-65.4c-0.8,-2.3 -0.7,-4.9 0.3,-7.1l39.4,-83.9c4,-8.4 17.1,-7.7 19.9,1.1l12.3,38.2 37.5,100.4c1,2.8 3.4,5 6.4,6l80,27.3c3.1,1.1 5.5,3.4 6.5,6.3z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="m386.7,253.5c0,-22.9 14.5,-42.6 35.3,-51.8 -1.5,-2.5 -2.4,-5.2 -2.4,-8.1 0,-11.1 12.8,-20.1 28.5,-20.1 0.4,0 0.7,0 1.1,0 6.5,-10.8 18.9,-18.1 33.1,-18.1 1,0 2,0 3,0.1 1.3,0.1 2.6,-0.5 3.3,-1.5 10.5,-16 37.1,-27.4 68.2,-27.4 11.5,0 22.4,1.6 32.1,4.3 2.3,-3.8 7.4,-6.4 13.3,-6.4 6.7,0 12.4,3.4 14.1,8.1 8.2,-9.5 22.1,-15.7 37.9,-15.7 25.2,0 45.6,15.9 45.6,35.5 0,2.4 -0.3,4.7 -0.9,7 -0.4,1.6 0.5,3.2 2.2,3.8 16.1,5.9 27,17.1 27,29.9 0,14.6 -14.1,27.1 -34,32 -1.6,0.4 -2.6,1.8 -2.6,3.3 0,0.1 0,0.2 0,0.3 0,11.3 -11.2,20.6 -25.6,21.6 0.1,0.5 0.1,1 0.1,1.6 0,21.7 -41.3,39.2 -92.2,39.2 -11,0 -21.5,-0.8 -31.2,-2.3 0,0.2 0,0.3 0,0.5 0,9 -11.6,16.3 -25.8,16.3 -0.8,0 -1.5,0 -2.2,-0.1 1,2.2 1.5,4.5 1.5,6.9 0,14 -17.7,25.3 -39.6,25.3 -2.4,0 -4.7,-0.1 -7,-0.4 -1.8,-0.2 -3.5,0.9 -3.9,2.6 -1.9,7 -8,12.1 -15.3,12.1 -8.8,0 -15.8,-7.5 -15.8,-16.7 0,-4.3 1.5,-8.2 4,-11.1 0.9,-1 1.2,-2.4 0.6,-3.6 -1.4,-2.6 -2,-5.3 -2,-8.2v0c0,-1.6 -1.3,-2.9 -2.9,-3.3 -27.1,-6 -47.5,-28.6 -47.5,-55.6z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="m870.4,883h-124.4c-3.6,0 -6.9,-1.8 -8.9,-4.6l-83.7,-117.7c-0.5,-0.8 -1,-1.6 -1.3,-2.5l-41.5,-121.2c-0.8,-2.4 -2.7,-4.5 -5.1,-5.7l-101.6,-51.3c-2.8,-1.4 -4.8,-4 -5.4,-6.9l-15,-74.4c-0.2,-1.2 -0.7,-2.4 -1.5,-3.5l-34.5,-50.7c-1.9,-2.8 -2.2,-6.2 -0.8,-9.2l21,-44.9c1.6,-3.4 5.1,-5.7 9.1,-5.9l39,-2.3c2.3,-0.1 4.4,-0.9 6.1,-2.3l28.7,-22.3c5.4,-4.2 13.6,-2.4 16.5,3.5l98.9,201.2c0.4,0.9 0.7,1.8 0.9,2.7l12.2,80.9c0.3,1.9 1.1,3.6 2.4,5l197,215.6c5.8,6.4 0.9,16.5 -8.1,16.5z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="m335.8,838.9c0.8,2.6 0.4,5.4 -1,7.7l-19.3,31.3c-1.9,3.1 -5.4,5.1 -9.2,5.1h-180.6c-8.4,0 -13.5,-8.8 -9,-15.4l116.3,-171.3c0.7,-1 1.1,-2.1 1.4,-3.2l53.3,-227.6c0.6,-2.7 2.4,-5 5,-6.4l72.2,-39.6c2.6,-1.4 4.4,-3.7 5,-6.5l9.7,-42.3c2,-8.8 14.6,-10.7 19.6,-3l3.5,5.6c1.5,2.4 1.9,5.4 0.9,8.1l-65.8,190.2c-0.5,1.5 -0.7,3.1 -0.4,4.7l16.4,91c0.3,1.8 0.1,3.7 -0.7,5.4l-39.1,87.8c-0.9,2.1 -1.1,4.4 -0.4,6.5z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="m424.22,657.05 l1580.54,-0.05c0.54,0 0,292 0,292l-1580.54,-0.03c-10.78,0 -19.46,-8.68 -19.46,-19.46l0,-252.99c0,-10.78 8.68,-19.46 19.46,-19.46z"
android:strokeAlpha="0.49803922"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#3f3f3f"
android:strokeColor="#00000000"
android:fillType="nonZero"
android:fillAlpha="1"
android:strokeLineCap="square"/>
<path
android:pathData="m728.71,710.91l0,19.89l-88.7,0l0,59.3l77.04,0L717.05,810l-77.04,0l0,65.39l89.84,0l0,19.9L616.56,895.29L616.56,791.16l-52.35,-52.35 -0.77,-0.18c5.41,6.64 9.65,14.32 12.69,23.09 3.72,10.39 5.62,21.92 5.7,34.6L581.84,809.87c-0.08,12.67 -1.98,24.25 -5.7,34.72 -3.63,10.39 -8.95,19.35 -15.97,26.87 -6.93,7.43 -15.46,13.26 -25.6,17.49 -7.54,3.1 -15.86,5.07 -24.97,5.89 -3.04,0.27 -6.16,0.42 -9.37,0.45L457.53,895.29l0,-6.55l-0.37,6.82 53.8,53.45l415.85,0c0.24,0 0.47,-0.02 0.69,-0.05L1132.91,948.97L953.5,769.55l-58.39,-58.39 -0.28,0.06 -58.03,184.06l-20.4,0l-44.66,-141.34zM783.29,711.07 L826.41,857.52 850.08,777.86zM509.6,711.29c1.52,0.15 3.01,0.33 4.49,0.54 -1.47,-0.21 -2.97,-0.39 -4.49,-0.54zM481.35,730.04l0,146.11l18.88,0c9.97,-0.08 18.59,-1.81 25.85,-5.19 7.27,-3.46 13.26,-8.15 17.99,-14.07 4.82,-5.91 8.36,-12.88 10.64,-20.91 2.37,-8.03 3.59,-16.73 3.68,-26.11l0,-13.81c-0.08,-9.38 -1.31,-18.04 -3.68,-25.98 -2.37,-8.03 -5.91,-14.95 -10.64,-20.78 -4.73,-5.91 -10.73,-10.56 -17.99,-13.94 -7.27,-3.38 -15.88,-5.15 -25.85,-5.32zM560.17,734.86c0.65,0.69 1.26,1.4 1.88,2.11 -0.61,-0.72 -1.23,-1.42 -1.88,-2.11z"
android:strokeAlpha="1"
android:strokeLineJoin="miter"
android:strokeWidth="1.94642854"
android:fillColor="#000000"
android:strokeColor="#00000000"
android:fillAlpha="0.18431373"
android:strokeLineCap="butt"/>
<path
android:pathData="m457.53,895.28l0,-184.51l42.7,0q19.26,0.25 34.34,6.59 15.21,6.21 25.6,17.49 10.52,11.15 15.97,26.86 5.58,15.59 5.7,34.59l0,13.56q-0.13,19.01 -5.7,34.72 -5.45,15.59 -15.97,26.86 -10.39,11.15 -25.6,17.49 -15.08,6.21 -34.34,6.34zM481.35,730.04l0,146.11l18.88,0q14.95,-0.13 25.85,-5.2 10.9,-5.2 17.99,-14.07 7.22,-8.87 10.64,-20.91 3.55,-12.04 3.67,-26.1l0,-13.81q-0.13,-14.07 -3.67,-25.98 -3.55,-12.04 -10.64,-20.78 -7.1,-8.87 -17.99,-13.94 -10.9,-5.07 -25.85,-5.32z"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillAlpha="1"/>
<path
android:pathData="M717.05,810L640.01,810l0,65.39l89.84,0l0,19.9l-113.29,0l0,-184.51l112.15,0l0,20.02L640.01,730.8l0,59.31l77.05,0z"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillAlpha="1"/>
<path
android:pathData="m826.41,857.52 l43.59,-146.74l24.96,0l-58.16,184.51L816.4,895.28l-58.29,-184.51l25.09,0z"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillAlpha="1"/>
</group>
</vector>

View File

@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="1926"
android:viewportHeight="1926">
<path
android:fillColor="#ad2a2a"
android:pathData="M2465,1904v561h-759L704,1463l-120,-120 -1,-1 5,-9 1,-3c9,-15 20,-29 31,-43l16,-19 3,-4 21,-30 3,-6c7,-11 12,-23 18,-35l14,-24 3,-4v-1a234,234 0,0 0,20 -53v-1l1,-3c4,-15 7,-31 13,-46l5,-9v-1c5,-10 11,-19 14, -30 2,-9 3,-19 3,-28v-1,-21l3,-17v-3l4,-17h1v-1c0,-2 -1,-4 -3,-4l8,-8 4,1c13,-4 25,-10 37,-17l8,-5 22,-16 9,-9v-1l5, -11c3,-9 2,-19 2,-29l6,-6 4,2 45,45 10,9 14,14 101,101 17,17 16,17 31,-31 -193,-191 1,-2 1,-2 -1,-3v-1l-1,-1 27,-27 192,-192 2,1a27,27 0,0 1,14 3l6,6c2,2 8,3 9,1l1310,1310z" />
<path
android:fillColor="#fff"
android:pathData="M1082,1260v4l-6,73c0,5 -5,9 -10,9H879c-4,0 -8,-2 -10,-5l-31,-58 -29,-71v-8l48,-94c2,-3 2,-5 1, -8l-24,-65c-1,-2 0,-5 1,-7l39,-84c4,-8 17,-8 20,1l12,38 38,101c1,2 3,5 6,6l80,27c3,1 6,3 7,6l45,135zM852,717c0,-23 15,-43 35,-52l-2,-8c0,-11 13,-20 29,-20h1a38,38 0,0 1,36 -18l3,-2c11,-16 37,-27 68,-27 12,0 23,2 32,4 3,-3 8,-6 14,-6s12,3 14,8c8,-9 22,-16 38,-16 25,0 45,16 45,36l-1,7 3,4c16,6 27,17 27,30 0,14 -15,27 -34,32 -2,0 -3,1 -3,3 0,11 -11,21 -26,22v1c0,22 -41,40 -92,40 -11,0 -21,-1 -31,-3v1c0,9 -12,16 -26,16h-2l2,7c0,14 -18,25 -40,25h-7l-4, 2c-2,7 -8,12 -15,12 -9,0 -16,-7 -16,-16 0,-5 1,-8 4,-11l1,-4c-2,-3 -2,-5 -2,-8 0,-2 -2,-3 -3,-3 -27,-6 -48,-29 -48,-56z" />
<path
android:fillColor="#fff"
android:pathData="M1336,1346h-125c-3,0 -6,-1 -8,-4l-84,-118 -1,-2 -42,-122 -5,-5 -102,-52 -5,-6 -15,-75 -2,-3 -34,-51c-2,-3 -2,-6 -1,-9l21,-45c2,-4 5,-6 9,-6l39,-2c3,0 5,-1 6,-3l29,-22c5,-4 14,-2 17,4l98,201 1,2 13,81 2,5 197,216c6,6 1,16 -8,16zM801,1302c1,3 1,6 -1,8l-19,31c-2,3 -5,5 -9,5H591c-8,0 -13,-8 -9,-15l116,-171 2,-3 53, -228c1,-3 3,-5 5,-6l72,-40c3,-1 5,-4 5,-7l10,-42c2,-9 15,-11 20,-3l3,6c2,2 2,5 1,8l-66,190v5l16,91v5l-40,88v6l22,72z" />
<path
android:fillColor="#3f3f3f"
android:pathData="M886.7,1119.5h1580.5c0.6,0 0,292 0,292H886.7a19.4,19.4 0,0 1,-19.5 -19.5v-253c0,-10.8 8.7,-19.5 19.5,-19.5z"
android:strokeWidth="4"
android:strokeAlpha=".5"
android:strokeColor="#000"
android:strokeLineCap="square"
android:strokeLineJoin="round" />
<path
android:fillAlpha=".2"
android:fillColor="#000"
android:pathData="M1191.2,1173.4v19.9h-88.7v59.3h77v19.9h-77v65.4h89.8v19.9L1079,1357.8v-104.2l-52.3,-52.3 -0.8, -0.2a75.1,75.1 0,0 1,12.7 23,104 104,0 0,1 5.7,34.7v13.5c0,12.7 -2,24.3 -5.7,34.8a72.8,72.8 0,0 1,-41.6 44.4,85.5 85.5,0 0,1 -34.3,6.3L920,1357.8v-6.6l-0.4,6.8 53.8,53.5h622L1416,1232l-58.4,-58.4h-0.3l-58,184.1h -20.4l-44.7,-141.3zM1245.8,1173.5l43,146.5 23.7,-79.7zM972.1,1173.8zM943.8,1192.5v146.1h18.9a62,62 0,0 0,25.8 -5.2,50.3 50.3,0 0,0 18,-14c4.9,-6 8.4,-13 10.7,-21 2.3,-8 3.6,-16.7 3.7,-26v-13.9c-0.1,-9.4 -1.4,-18 -3.7,-26 -2.4,-8 -6,-15 -10.7,-20.7a49.3,49.3 0,0 0,-18 -14,63.4 63.4,0 0,0 -25.8,-5.3zM1022.6,1197.3l2,2.1 -2,-2z"
android:strokeWidth="1.9"
android:strokeColor="#000" />
<path
android:fillColor="#fff"
android:pathData="M920,1357.7v-184.5h42.7q19.3,0.3 34.3,6.6 15.2,6.2 25.6,17.5 10.6,11.2 16,26.9 5.6,15.6 5.7, 34.6v13.5q-0.1,19 -5.7,34.7 -5.4,15.6 -16,26.9 -10.4,11.2 -25.6,17.5 -15,6.2 -34.3,6.3zM943.8,1192.5v146.1h18.9q15, -0.1 25.8,-5.2 11,-5.2 18,-14 7.3,-9 10.7,-21 3.5,-12 3.6,-26v-13.9q0,-14 -3.6,-26t-10.7,-20.7q-7,-9 -18,-14 -10.9,-5 -25.8,-5.3zM1179.5,1272.5h-77v65.4h89.8v19.9L1079,1357.8v-184.6h112.2v20h-88.7v59.4h77zM1288.9, 1320l43.6,-146.8h25l-58.2,184.6h-20.4l-58.3,-184.6h25z"
android:strokeWidth="1"
android:strokeColor="#000" />
</vector>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/> <background android:drawable="@color/colorPrimary" />
<foreground android:drawable="@drawable/ic_launcher_foreground"/> <foreground android:drawable="@drawable/ic_launcher_foreground_dev" />
</adaptive-icon> </adaptive-icon>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/> <background android:drawable="@color/colorPrimary" />
<foreground android:drawable="@drawable/ic_launcher_foreground"/> <foreground android:drawable="@drawable/ic_launcher_foreground_dev" />
</adaptive-icon> </adaptive-icon>

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#D32F2F</color>
</resources>

View File

@ -43,6 +43,7 @@
android:name=".ui.modules.message.send.SendMessageActivity" android:name=".ui.modules.message.send.SendMessageActivity"
android:configChanges="orientation|screenSize" android:configChanges="orientation|screenSize"
android:label="@string/send_message_title" android:label="@string/send_message_title"
android:windowSoftInputMode="adjustResize"
android:theme="@style/WulkanowyTheme.NoActionBar" /> android:theme="@style/WulkanowyTheme.NoActionBar" />
<activity <activity
android:name=".ui.modules.timetablewidget.TimetableWidgetConfigureActivity" android:name=".ui.modules.timetablewidget.TimetableWidgetConfigureActivity"

View File

@ -13,6 +13,7 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.utils.Log import eu.davidea.flexibleadapter.utils.Log
import io.github.wulkanowy.di.DaggerAppComponent import io.github.wulkanowy.di.DaggerAppComponent
import io.github.wulkanowy.services.sync.SyncWorkerFactory import io.github.wulkanowy.services.sync.SyncWorkerFactory
import io.github.wulkanowy.ui.base.ThemeManager
import io.github.wulkanowy.utils.ActivityLifecycleLogger import io.github.wulkanowy.utils.ActivityLifecycleLogger
import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.CrashlyticsTree import io.github.wulkanowy.utils.CrashlyticsTree
@ -29,6 +30,9 @@ class WulkanowyApp : DaggerApplication() {
@Inject @Inject
lateinit var workerFactory: SyncWorkerFactory lateinit var workerFactory: SyncWorkerFactory
@Inject
lateinit var themeManager: ThemeManager
@Inject @Inject
lateinit var appInfo: AppInfo lateinit var appInfo: AppInfo
@ -41,6 +45,7 @@ class WulkanowyApp : DaggerApplication() {
super.onCreate() super.onCreate()
AndroidThreeTen.init(this) AndroidThreeTen.init(this)
RxJavaPlugins.setErrorHandler(::onError) RxJavaPlugins.setErrorHandler(::onError)
themeManager.applyDefaultTheme()
initWorkManager() initWorkManager()
initLogging() initLogging()

View File

@ -6,14 +6,15 @@ import io.github.wulkanowy.di.scopes.PerActivity
import io.github.wulkanowy.ui.modules.login.LoginActivity import io.github.wulkanowy.ui.modules.login.LoginActivity
import io.github.wulkanowy.ui.modules.login.LoginModule import io.github.wulkanowy.ui.modules.login.LoginModule
import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetConfigureActivity import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetConfigureActivity
import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetProvider
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainModule import io.github.wulkanowy.ui.modules.main.MainModule
import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity
import io.github.wulkanowy.ui.modules.splash.SplashActivity import io.github.wulkanowy.ui.modules.splash.SplashActivity
import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetProvider
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetConfigureActivity import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetConfigureActivity
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider
@Suppress("unused")
@Module @Module
internal abstract class BuilderModule { internal abstract class BuilderModule {

View File

@ -28,6 +28,7 @@ import io.github.wulkanowy.services.sync.works.Work
import io.github.wulkanowy.services.widgets.TimetableWidgetService import io.github.wulkanowy.services.widgets.TimetableWidgetService
import javax.inject.Singleton import javax.inject.Singleton
@Suppress("unused")
@AssistedModule @AssistedModule
@Module(includes = [AssistedInject_ServicesModule::class]) @Module(includes = [AssistedInject_ServicesModule::class])
abstract class ServicesModule { abstract class ServicesModule {

View File

@ -64,7 +64,7 @@ class SyncWorker @AssistedInject constructor(
private fun notify(result: Result) { private fun notify(result: Result) {
notificationManager.notify(Random.nextInt(Int.MAX_VALUE), NotificationCompat.Builder(applicationContext, DebugChannel.CHANNEL_ID) notificationManager.notify(Random.nextInt(Int.MAX_VALUE), NotificationCompat.Builder(applicationContext, DebugChannel.CHANNEL_ID)
.setContentTitle("Debug notification") .setContentTitle("Debug notification")
.setSmallIcon(R.drawable.ic_more_settings_24dp) .setSmallIcon(R.drawable.ic_more_settings)
.setAutoCancel(true) .setAutoCancel(true)
.setColor(applicationContext.getCompatColor(R.color.colorPrimary)) .setColor(applicationContext.getCompatColor(R.color.colorPrimary))
.setStyle(BigTextStyle().bigText("${SyncWorker::class.java.simpleName} result: $result")) .setStyle(BigTextStyle().bigText("${SyncWorker::class.java.simpleName} result: $result"))

View File

@ -15,7 +15,7 @@ import io.github.wulkanowy.data.repositories.grade.GradeRepository
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
import io.github.wulkanowy.services.sync.channels.NewEntriesChannel import io.github.wulkanowy.services.sync.channels.NewEntriesChannel
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView.MenuView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.getCompatColor import io.github.wulkanowy.utils.getCompatColor
import io.reactivex.Completable import io.reactivex.Completable
import javax.inject.Inject import javax.inject.Inject
@ -41,14 +41,14 @@ class GradeWork @Inject constructor(
notificationManager.notify(Random.nextInt(Int.MAX_VALUE), NotificationCompat.Builder(context, NewEntriesChannel.CHANNEL_ID) notificationManager.notify(Random.nextInt(Int.MAX_VALUE), NotificationCompat.Builder(context, NewEntriesChannel.CHANNEL_ID)
.setContentTitle(context.resources.getQuantityString(R.plurals.grade_new_items, grades.size, grades.size)) .setContentTitle(context.resources.getQuantityString(R.plurals.grade_new_items, grades.size, grades.size))
.setContentText(context.resources.getQuantityString(R.plurals.grade_notify_new_items, grades.size, grades.size)) .setContentText(context.resources.getQuantityString(R.plurals.grade_notify_new_items, grades.size, grades.size))
.setSmallIcon(R.drawable.ic_stat_notify_grade) .setSmallIcon(R.drawable.ic_stat_grade)
.setAutoCancel(true) .setAutoCancel(true)
.setPriority(PRIORITY_HIGH) .setPriority(PRIORITY_HIGH)
.setDefaults(DEFAULT_ALL) .setDefaults(DEFAULT_ALL)
.setColor(context.getCompatColor(R.color.colorPrimary)) .setColor(context.getCompatColor(R.color.colorPrimary))
.setContentIntent( .setContentIntent(
PendingIntent.getActivity(context, MenuView.GRADE.id, PendingIntent.getActivity(context, MainView.Section.GRADE.id,
MainActivity.getStartIntent(context, MenuView.GRADE, true), FLAG_UPDATE_CURRENT)) MainActivity.getStartIntent(context, MainView.Section.GRADE, true), FLAG_UPDATE_CURRENT))
.setStyle(NotificationCompat.InboxStyle().run { .setStyle(NotificationCompat.InboxStyle().run {
setSummaryText(context.resources.getQuantityString(R.plurals.grade_number_item, grades.size, grades.size)) setSummaryText(context.resources.getQuantityString(R.plurals.grade_number_item, grades.size, grades.size))
grades.forEach { addLine("${it.subject}: ${it.entry}") } grades.forEach { addLine("${it.subject}: ${it.entry}") }

View File

@ -15,7 +15,7 @@ import io.github.wulkanowy.data.repositories.luckynumber.LuckyNumberRepository
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
import io.github.wulkanowy.services.sync.channels.NewEntriesChannel import io.github.wulkanowy.services.sync.channels.NewEntriesChannel
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView.MenuView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.getCompatColor import io.github.wulkanowy.utils.getCompatColor
import io.reactivex.Completable import io.reactivex.Completable
import javax.inject.Inject import javax.inject.Inject
@ -41,14 +41,14 @@ class LuckyNumberWork @Inject constructor(
notificationManager.notify(Random.nextInt(Int.MAX_VALUE), NotificationCompat.Builder(context, NewEntriesChannel.CHANNEL_ID) notificationManager.notify(Random.nextInt(Int.MAX_VALUE), NotificationCompat.Builder(context, NewEntriesChannel.CHANNEL_ID)
.setContentTitle(context.getString(R.string.lucky_number_notify_new_item_title)) .setContentTitle(context.getString(R.string.lucky_number_notify_new_item_title))
.setContentText(context.getString(R.string.lucky_number_notify_new_item, luckyNumber.luckyNumber)) .setContentText(context.getString(R.string.lucky_number_notify_new_item, luckyNumber.luckyNumber))
.setSmallIcon(R.drawable.ic_stat_notify_lucky_number) .setSmallIcon(R.drawable.ic_stat_luckynumber)
.setAutoCancel(true) .setAutoCancel(true)
.setDefaults(DEFAULT_ALL) .setDefaults(DEFAULT_ALL)
.setPriority(PRIORITY_HIGH) .setPriority(PRIORITY_HIGH)
.setColor(context.getCompatColor(R.color.colorPrimary)) .setColor(context.getCompatColor(R.color.colorPrimary))
.setContentIntent( .setContentIntent(
PendingIntent.getActivity(context, MenuView.MESSAGE.id, PendingIntent.getActivity(context, MainView.Section.MESSAGE.id,
MainActivity.getStartIntent(context, MenuView.LUCKY_NUMBER, true), FLAG_UPDATE_CURRENT)) MainActivity.getStartIntent(context, MainView.Section.LUCKY_NUMBER, true), FLAG_UPDATE_CURRENT))
.build()) .build())
} }
} }

View File

@ -16,7 +16,7 @@ import io.github.wulkanowy.data.repositories.message.MessageRepository
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
import io.github.wulkanowy.services.sync.channels.NewEntriesChannel import io.github.wulkanowy.services.sync.channels.NewEntriesChannel
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView.MenuView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.getCompatColor import io.github.wulkanowy.utils.getCompatColor
import io.reactivex.Completable import io.reactivex.Completable
import javax.inject.Inject import javax.inject.Inject
@ -42,14 +42,14 @@ class MessageWork @Inject constructor(
notificationManager.notify(Random.nextInt(Int.MAX_VALUE), NotificationCompat.Builder(context, NewEntriesChannel.CHANNEL_ID) notificationManager.notify(Random.nextInt(Int.MAX_VALUE), NotificationCompat.Builder(context, NewEntriesChannel.CHANNEL_ID)
.setContentTitle(context.resources.getQuantityString(R.plurals.message_new_items, messages.size, messages.size)) .setContentTitle(context.resources.getQuantityString(R.plurals.message_new_items, messages.size, messages.size))
.setContentText(context.resources.getQuantityString(R.plurals.message_notify_new_items, messages.size, messages.size)) .setContentText(context.resources.getQuantityString(R.plurals.message_notify_new_items, messages.size, messages.size))
.setSmallIcon(R.drawable.ic_stat_notify_message) .setSmallIcon(R.drawable.ic_stat_message)
.setAutoCancel(true) .setAutoCancel(true)
.setDefaults(DEFAULT_ALL) .setDefaults(DEFAULT_ALL)
.setPriority(PRIORITY_HIGH) .setPriority(PRIORITY_HIGH)
.setColor(context.getCompatColor(R.color.colorPrimary)) .setColor(context.getCompatColor(R.color.colorPrimary))
.setContentIntent( .setContentIntent(
PendingIntent.getActivity(context, MenuView.MESSAGE.id, PendingIntent.getActivity(context, MainView.Section.MESSAGE.id,
MainActivity.getStartIntent(context, MenuView.MESSAGE, true), FLAG_UPDATE_CURRENT) MainActivity.getStartIntent(context, MainView.Section.MESSAGE, true), FLAG_UPDATE_CURRENT)
) )
.setStyle(NotificationCompat.InboxStyle().run { .setStyle(NotificationCompat.InboxStyle().run {
setSummaryText(context.resources.getQuantityString(R.plurals.message_number_item, messages.size, messages.size)) setSummaryText(context.resources.getQuantityString(R.plurals.message_number_item, messages.size, messages.size))

View File

@ -15,7 +15,7 @@ import io.github.wulkanowy.data.repositories.note.NoteRepository
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
import io.github.wulkanowy.services.sync.channels.NewEntriesChannel import io.github.wulkanowy.services.sync.channels.NewEntriesChannel
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView.MenuView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.getCompatColor import io.github.wulkanowy.utils.getCompatColor
import io.reactivex.Completable import io.reactivex.Completable
import javax.inject.Inject import javax.inject.Inject
@ -41,14 +41,14 @@ class NoteWork @Inject constructor(
notificationManager.notify(Random.nextInt(Int.MAX_VALUE), NotificationCompat.Builder(context, NewEntriesChannel.CHANNEL_ID) notificationManager.notify(Random.nextInt(Int.MAX_VALUE), NotificationCompat.Builder(context, NewEntriesChannel.CHANNEL_ID)
.setContentTitle(context.resources.getQuantityString(R.plurals.note_new_items, notes.size, notes.size)) .setContentTitle(context.resources.getQuantityString(R.plurals.note_new_items, notes.size, notes.size))
.setContentText(context.resources.getQuantityString(R.plurals.note_notify_new_items, notes.size, notes.size)) .setContentText(context.resources.getQuantityString(R.plurals.note_notify_new_items, notes.size, notes.size))
.setSmallIcon(R.drawable.ic_stat_notify_note) .setSmallIcon(R.drawable.ic_stat_note)
.setAutoCancel(true) .setAutoCancel(true)
.setDefaults(DEFAULT_ALL) .setDefaults(DEFAULT_ALL)
.setPriority(PRIORITY_HIGH) .setPriority(PRIORITY_HIGH)
.setColor(context.getCompatColor(R.color.colorPrimary)) .setColor(context.getCompatColor(R.color.colorPrimary))
.setContentIntent( .setContentIntent(
PendingIntent.getActivity(context, MenuView.NOTE.id, PendingIntent.getActivity(context, MainView.Section.NOTE.id,
MainActivity.getStartIntent(context, MenuView.NOTE, true), FLAG_UPDATE_CURRENT)) MainActivity.getStartIntent(context, MainView.Section.NOTE, true), FLAG_UPDATE_CURRENT))
.setStyle(NotificationCompat.InboxStyle().run { .setStyle(NotificationCompat.InboxStyle().run {
setSummaryText(context.resources.getQuantityString(R.plurals.note_number_item, notes.size, notes.size)) setSummaryText(context.resources.getQuantityString(R.plurals.note_number_item, notes.size, notes.size))
notes.forEach { addLine("${it.teacher}: ${it.category}") } notes.forEach { addLine("${it.teacher}: ${it.category}") }

View File

@ -1,5 +1,8 @@
package io.github.wulkanowy.ui.base package io.github.wulkanowy.ui.base
import android.app.ActivityManager
import android.os.Build.VERSION.SDK_INT
import android.os.Build.VERSION_CODES.LOLLIPOP
import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.os.Bundle import android.os.Bundle
@ -16,6 +19,7 @@ import dagger.android.HasAndroidInjector
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.ui.modules.login.LoginActivity import io.github.wulkanowy.ui.modules.login.LoginActivity
import io.github.wulkanowy.utils.FragmentLifecycleLogger import io.github.wulkanowy.utils.FragmentLifecycleLogger
import io.github.wulkanowy.utils.getThemeAttrColor
import javax.inject.Inject import javax.inject.Inject
abstract class BaseActivity<T : BasePresenter<out BaseView>> : AppCompatActivity(), BaseView, HasAndroidInjector { abstract class BaseActivity<T : BasePresenter<out BaseView>> : AppCompatActivity(), BaseView, HasAndroidInjector {
@ -35,10 +39,15 @@ abstract class BaseActivity<T : BasePresenter<out BaseView>> : AppCompatActivity
public override fun onCreate(savedInstanceState: Bundle?) { public override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this) AndroidInjection.inject(this)
themeManager.applyTheme(this) themeManager.applyActivityTheme(this)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleLogger, true) supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleLogger, true)
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true) AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
if (SDK_INT >= LOLLIPOP) {
@Suppress("DEPRECATION")
setTaskDescription(ActivityManager.TaskDescription(null, null, getThemeAttrColor(R.attr.colorSurface)))
}
} }
override fun showError(text: String, error: Throwable) { override fun showError(text: String, error: Throwable) {

View File

@ -2,27 +2,29 @@ package io.github.wulkanowy.ui.base
import android.content.pm.PackageManager.GET_ACTIVITIES import android.content.pm.PackageManager.GET_ACTIVITIES
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class ThemeManager @Inject constructor(private val preferencesRepository: PreferencesRepository) { class ThemeManager @Inject constructor(private val preferencesRepository: PreferencesRepository) {
fun applyTheme(activity: AppCompatActivity) { fun applyActivityTheme(activity: AppCompatActivity) {
if (isThemeApplicable(activity)) { if (isThemeApplicable(activity)) {
activity.delegate.apply { applyDefaultTheme()
when (preferencesRepository.appTheme) { if (preferencesRepository.appTheme == "black") activity.setTheme(R.style.WulkanowyTheme_Black)
"light" -> setLocalNightMode(MODE_NIGHT_NO)
"dark" -> setLocalNightMode(MODE_NIGHT_YES)
"black" -> {
setLocalNightMode(MODE_NIGHT_YES)
activity.setTheme(R.style.WulkanowyTheme_Black)
}
}
} }
} }
fun applyDefaultTheme() {
AppCompatDelegate.setDefaultNightMode(
if (preferencesRepository.appTheme == "light") MODE_NIGHT_NO
else MODE_NIGHT_YES
)
} }
private fun isThemeApplicable(activity: AppCompatActivity): Boolean { private fun isThemeApplicable(activity: AppCompatActivity): Boolean {

View File

@ -1,19 +1,29 @@
package io.github.wulkanowy.ui.modules.about package io.github.wulkanowy.ui.modules.about
import android.content.Intent import android.content.Intent
import android.content.Intent.ACTION_SENDTO
import android.content.Intent.EXTRA_EMAIL
import android.content.Intent.EXTRA_SUBJECT
import android.content.Intent.EXTRA_TEXT
import android.graphics.drawable.Drawable
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import com.mikepenz.aboutlibraries.LibsBuilder import eu.davidea.flexibleadapter.FlexibleAdapter
import com.mikepenz.aboutlibraries.LibsFragmentCompat import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.about.license.LicenseFragment
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.getCompatDrawable
import io.github.wulkanowy.utils.openInternetBrowser import io.github.wulkanowy.utils.openInternetBrowser
import io.github.wulkanowy.utils.withOnExtraListener import io.github.wulkanowy.utils.setOnItemClickListener
import kotlinx.android.synthetic.main.fragment_about.*
import javax.inject.Inject import javax.inject.Inject
class AboutFragment : BaseFragment(), AboutView, MainView.TitledView { class AboutFragment : BaseFragment(), AboutView, MainView.TitledView {
@ -22,58 +32,89 @@ class AboutFragment : BaseFragment(), AboutView, MainView.TitledView {
lateinit var presenter: AboutPresenter lateinit var presenter: AboutPresenter
@Inject @Inject
lateinit var fragmentCompat: LibsFragmentCompat lateinit var aboutAdapter: FlexibleAdapter<AbstractFlexibleItem<*>>
@Inject @Inject
lateinit var appInfo: AppInfo lateinit var appInfo: AppInfo
override val versionRes: Triple<String, String, Drawable?>?
get() = context?.run {
Triple(getString(R.string.about_version), "${appInfo.versionName} (${appInfo.versionCode})", getCompatDrawable(R.drawable.ic_all_about))
}
override val feedbackRes: Triple<String, String, Drawable?>?
get() = context?.run {
Triple(getString(R.string.about_feedback), getString(R.string.about_feedback_summary), getCompatDrawable(R.drawable.ic_about_feedback))
}
override val discordRes: Triple<String, String, Drawable?>?
get() = context?.run {
Triple(getString(R.string.about_discord), getString(R.string.about_discord_summary), getCompatDrawable(R.drawable.ic_about_discord))
}
override val homepageRes: Triple<String, String, Drawable?>?
get() = context?.run {
Triple(getString(R.string.about_homepage), getString(R.string.about_homepage_summary), getCompatDrawable(R.drawable.ic_about_homepage))
}
override val licensesRes: Triple<String, String, Drawable?>?
get() = context?.run {
Triple(getString(R.string.about_licenses), getString(R.string.about_licenses_summary), getCompatDrawable(R.drawable.ic_about_licenses))
}
override val privacyRes: Triple<String, String, Drawable?>?
get() = context?.run {
Triple(getString(R.string.about_privacy), getString(R.string.about_privacy_summary), getCompatDrawable(R.drawable.ic_about_privacy))
}
override val titleStringId get() = R.string.about_title
companion object { companion object {
fun newInstance() = AboutFragment() fun newInstance() = AboutFragment()
} }
override val titleStringId: Int
get() = R.string.about_title
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
presenter.onAttachView(this) return inflater.inflate(R.layout.fragment_about, container, false)
return Bundle().apply {
putSerializable("data", LibsBuilder()
.withAboutAppName(getString(R.string.app_name))
.withAboutVersionShown(true)
.withAboutIconShown(true)
.withLicenseShown(true)
.withAboutSpecial1(getString(R.string.about_discord_invite))
.withAboutSpecial2(getString(R.string.about_homepage))
.withAboutSpecial3(getString(R.string.about_feedback))
.withFields(R.string::class.java.fields)
.withCheckCachedDetection(false)
.withExcludedLibraries("fastadapter", "AndroidIconics", "Jsoup", "Retrofit", "okio",
"Butterknife", "CircleImageView")
.withOnExtraListener { presenter.onExtraSelect(it) })
}.let {
fragmentCompat.onCreateView(inflater.context, inflater, container, savedInstanceState, it)
}
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
fragmentCompat.onViewCreated(view, savedInstanceState) presenter.onAttachView(this)
} }
override fun openDiscordInviteView() { override fun initView() {
aboutAdapter.setOnItemClickListener(presenter::onItemSelected)
with(aboutRecycler) {
layoutManager = SmoothScrollLinearLayoutManager(context)
adapter = aboutAdapter
}
}
override fun updateData(header: AboutScrollableHeader, items: List<AboutItem>) {
with(aboutAdapter) {
removeAllScrollableHeaders()
addScrollableHeader(header)
updateDataSet(items)
}
}
override fun openDiscordInvite() {
context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage) context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage)
} }
override fun openHomepageWebView() { override fun openHomepage() {
context?.openInternetBrowser("https://wulkanowy.github.io/", ::showMessage) context?.openInternetBrowser("https://wulkanowy.github.io/", ::showMessage)
} }
override fun openEmailClientView() { override fun openEmailClient() {
val intent = Intent(Intent.ACTION_SENDTO).apply { val intent = Intent(ACTION_SENDTO)
.apply {
data = Uri.parse("mailto:") data = Uri.parse("mailto:")
putExtra(Intent.EXTRA_EMAIL, Array(1) { "wulkanowyinc@gmail.com" }) putExtra(EXTRA_EMAIL, arrayOf("wulkanowyinc@gmail.com"))
putExtra(Intent.EXTRA_SUBJECT, "Zgłoszenie błędu") putExtra(EXTRA_SUBJECT, "Zgłoszenie błędu")
putExtra(Intent.EXTRA_TEXT, "Tu umieść treść zgłoszenia\n\n" + "-".repeat(40) + "\n" + """ putExtra(EXTRA_TEXT, "Tu umieść treść zgłoszenia\n\n${"-".repeat(40)}\n " +
"""
Build: ${appInfo.versionCode} Build: ${appInfo.versionCode}
SDK: ${appInfo.systemVersion} SDK: ${appInfo.systemVersion}
Device: ${appInfo.systemManufacturer} ${appInfo.systemModel} Device: ${appInfo.systemManufacturer} ${appInfo.systemModel}
@ -89,8 +130,15 @@ class AboutFragment : BaseFragment(), AboutView, MainView.TitledView {
} }
} }
override fun openLicenses() {
(activity as? MainActivity)?.pushView(LicenseFragment.newInstance())
}
override fun openPrivacyPolicy() {
context?.openInternetBrowser("https://wulkanowy.github.io/polityka-prywatnosci.html", ::showMessage)
}
override fun onDestroyView() { override fun onDestroyView() {
fragmentCompat.onDestroyView()
presenter.onDetachView() presenter.onDetachView()
super.onDestroyView() super.onDestroyView()
} }

View File

@ -0,0 +1,56 @@
package io.github.wulkanowy.ui.modules.about
import android.graphics.drawable.Drawable
import android.view.View
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.viewholders.FlexibleViewHolder
import io.github.wulkanowy.R
import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.main.item_about.*
class AboutItem(
val title: String,
private val summary: String,
private val image: Drawable?
) : AbstractFlexibleItem<AboutItem.ViewHolder>() {
override fun getLayoutRes() = R.layout.item_about
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<*>>) = ViewHolder(view, adapter)
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>, holder: ViewHolder, position: Int, payloads: MutableList<Any>) {
with(holder) {
aboutItemImage.setImageDrawable(image)
aboutItemTitle.text = title
aboutItemSummary.text = summary
}
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as AboutItem
if (title != other.title) return false
if (summary != other.summary) return false
if (image != other.image) return false
return true
}
override fun hashCode(): Int {
var result = title.hashCode()
result = 31 * result + summary.hashCode()
result = 31 * result + (image?.hashCode() ?: 0)
return result
}
class ViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<*>>) : FlexibleViewHolder(view, adapter),
LayoutContainer {
override val containerView: View? get() = contentView
}
}

View File

@ -1,14 +0,0 @@
package io.github.wulkanowy.ui.modules.about
import com.mikepenz.aboutlibraries.LibsFragmentCompat
import dagger.Module
import dagger.Provides
import io.github.wulkanowy.di.scopes.PerFragment
@Module
class AboutModule {
@PerFragment
@Provides
fun provideLibsFragmentCompat() = LibsFragmentCompat()
}

View File

@ -1,9 +1,6 @@
package io.github.wulkanowy.ui.modules.about package io.github.wulkanowy.ui.modules.about
import com.mikepenz.aboutlibraries.Libs import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import com.mikepenz.aboutlibraries.Libs.SpecialButton.SPECIAL1
import com.mikepenz.aboutlibraries.Libs.SpecialButton.SPECIAL2
import com.mikepenz.aboutlibraries.Libs.SpecialButton.SPECIAL3
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
@ -21,28 +18,53 @@ class AboutPresenter @Inject constructor(
override fun onAttachView(view: AboutView) { override fun onAttachView(view: AboutView) {
super.onAttachView(view) super.onAttachView(view)
view.initView()
Timber.i("About view was initialized") Timber.i("About view was initialized")
loadData()
} }
fun onExtraSelect(type: Libs.SpecialButton?) { fun onItemSelected(item: AbstractFlexibleItem<*>) {
if (item !is AboutItem) return
view?.run { view?.run {
when (type) { when (item.title) {
SPECIAL1 -> { feedbackRes?.first -> {
Timber.i("Opening discord invide page")
analytics.logEvent("open_page", "name" to "discord")
openDiscordInviteView()
}
SPECIAL2 -> {
Timber.i("Opening home page")
analytics.logEvent("open_page", "name" to "home")
openHomepageWebView()
}
SPECIAL3 -> {
Timber.i("Opening email client ") Timber.i("Opening email client ")
analytics.logEvent("open_page", "name" to "email") openEmailClient()
openEmailClientView() analytics.logEvent("about_open", "name" to "feedback")
}
discordRes?.first -> {
Timber.i("Opening discord")
openDiscordInvite()
analytics.logEvent("about_open", "name" to "discord")
}
homepageRes?.first -> {
Timber.i("Opening homepage")
openHomepage()
analytics.logEvent("about_open", "name" to "homepage")
}
licensesRes?.first -> {
Timber.i("Opening licenses view")
openLicenses()
analytics.logEvent("about_open", "name" to "licenses")
}
privacyRes?.first -> {
Timber.i("Opening privacy page ")
openPrivacyPolicy()
analytics.logEvent("about_open", "name" to "privacy")
} }
} }
} }
} }
private fun loadData() {
view?.run {
updateData(AboutScrollableHeader(), listOfNotNull(
versionRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
feedbackRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
discordRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
homepageRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
licensesRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
privacyRes?.let { (title, summary, image) -> AboutItem(title, summary, image) }))
}
}
} }

View File

@ -0,0 +1,41 @@
package io.github.wulkanowy.ui.modules.about
import android.view.View
import androidx.core.content.res.ResourcesCompat
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.viewholders.FlexibleViewHolder
import io.github.wulkanowy.R
import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.main.scrollable_header_about.*
class AboutScrollableHeader : AbstractFlexibleItem<AboutScrollableHeader.ViewHolder>() {
override fun getLayoutRes() = R.layout.scrollable_header_about
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<*>>) = ViewHolder(view, adapter)
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>, holder: ViewHolder, position: Int, payloads: MutableList<Any>) {
with(holder) {
val context = contentView.context
val drawable = ResourcesCompat.getDrawableForDensity(context.resources, context.applicationInfo.icon, 640, null)
aboutScrollableHeaderIcon.setImageDrawable(drawable)
}
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
return true
}
override fun hashCode() = javaClass.hashCode()
class ViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<*>>) : FlexibleViewHolder(view, adapter),
LayoutContainer {
override val containerView: View? get() = contentView
}
}

View File

@ -1,12 +1,33 @@
package io.github.wulkanowy.ui.modules.about package io.github.wulkanowy.ui.modules.about
import android.graphics.drawable.Drawable
import io.github.wulkanowy.ui.base.BaseView import io.github.wulkanowy.ui.base.BaseView
interface AboutView : BaseView { interface AboutView : BaseView {
fun openDiscordInviteView() val versionRes: Triple<String, String, Drawable?>?
fun openEmailClientView() val feedbackRes: Triple<String, String, Drawable?>?
fun openHomepageWebView() val discordRes: Triple<String, String, Drawable?>?
val homepageRes: Triple<String, String, Drawable?>?
val licensesRes: Triple<String, String, Drawable?>?
val privacyRes: Triple<String, String, Drawable?>?
fun initView()
fun updateData(header: AboutScrollableHeader, items: List<AboutItem>)
fun openDiscordInvite()
fun openEmailClient()
fun openHomepage()
fun openLicenses()
fun openPrivacyPolicy()
} }

View File

@ -0,0 +1,87 @@
package io.github.wulkanowy.ui.modules.about.license
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.View.GONE
import android.view.View.VISIBLE
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import androidx.core.text.HtmlCompat
import androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY
import com.mikepenz.aboutlibraries.Libs
import com.mikepenz.aboutlibraries.entity.Library
import dagger.Lazy
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import io.github.wulkanowy.R
import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.setOnItemClickListener
import kotlinx.android.synthetic.main.fragment_license.*
import javax.inject.Inject
class LicenseFragment : BaseFragment(), LicenseView, MainView.TitledView {
@Inject
lateinit var presenter: LicensePresenter
@Inject
lateinit var licenseAdapter: FlexibleAdapter<AbstractFlexibleItem<*>>
@Inject
lateinit var libs: Lazy<Libs>
override val titleStringId get() = R.string.license_title
override val appLibraries: ArrayList<Library>?
get() = context?.let {
libs.get().prepareLibraries(it, emptyArray(), emptyArray(), autoDetect = true, checkCachedDetection = true, sort = true)
}
companion object {
fun newInstance() = LicenseFragment()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_license, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
presenter.onAttachView(this)
}
override fun initView() {
with(licenseRecycler) {
layoutManager = SmoothScrollLinearLayoutManager(context)
adapter = licenseAdapter
}
licenseAdapter.setOnItemClickListener(presenter::onItemSelected)
}
override fun updateData(data: List<LicenseItem>) {
licenseAdapter.updateDataSet(data)
}
override fun openLicense(licenseHtml: String) {
context?.let {
AlertDialog.Builder(it).apply {
setTitle(R.string.license_dialog_title)
setMessage(HtmlCompat.fromHtml(licenseHtml, FROM_HTML_MODE_LEGACY))
setPositiveButton(android.R.string.ok) { _, _ -> }
show()
}
}
}
override fun showProgress(show: Boolean) {
licenseProgress.visibility = if (show) VISIBLE else GONE
}
override fun onDestroyView() {
presenter.onDetachView()
super.onDestroyView()
}
}

View File

@ -0,0 +1,44 @@
package io.github.wulkanowy.ui.modules.about.license
import android.view.View
import com.mikepenz.aboutlibraries.entity.Library
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.viewholders.FlexibleViewHolder
import io.github.wulkanowy.R
import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.main.item_license.*
class LicenseItem(val library: Library) : AbstractFlexibleItem<LicenseItem.ViewHolder>() {
override fun getLayoutRes() = R.layout.item_license
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<*>>) = ViewHolder(view, adapter)
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>, holder: ViewHolder, position: Int, payloads: MutableList<Any>) {
with(holder) {
licenseItemName.text = library.libraryName
licenseItemSummary.text = library.license?.licenseName
}
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as LicenseItem
if (library != other.library) return false
return true
}
override fun hashCode() = library.hashCode()
class ViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<*>>) : FlexibleViewHolder(view, adapter),
LayoutContainer {
override val containerView: View? get() = contentView
}
}

View File

@ -0,0 +1,15 @@
package io.github.wulkanowy.ui.modules.about.license
import android.content.Context
import com.mikepenz.aboutlibraries.Libs
import dagger.Module
import dagger.Provides
import io.github.wulkanowy.di.scopes.PerFragment
@Module
class LicenseModule {
@PerFragment
@Provides
fun provideLibs(context: Context) = Libs(context)
}

View File

@ -0,0 +1,40 @@
package io.github.wulkanowy.ui.modules.about.license
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.SchedulersProvider
import io.reactivex.Single
import javax.inject.Inject
class LicensePresenter @Inject constructor(
schedulers: SchedulersProvider,
errorHandler: ErrorHandler,
studentRepository: StudentRepository
) : BasePresenter<LicenseView>(errorHandler, studentRepository, schedulers) {
override fun onAttachView(view: LicenseView) {
super.onAttachView(view)
view.initView()
loadData()
}
fun onItemSelected(item: AbstractFlexibleItem<*>) {
if (item !is LicenseItem) return
view?.run { item.library.license?.licenseDescription?.let { openLicense(it) } }
}
private fun loadData() {
disposable.add(Single.fromCallable { view?.appLibraries }
.map {
val exclude = listOf("Android-Iconics", "CircleImageView", "FastAdapter", "Jsoup", "okio", "Retrofit")
it.filter { library -> !exclude.contains(library.libraryName) }
}
.map { it.map { library -> LicenseItem(library) } }
.subscribeOn(schedulers.backgroundThread)
.observeOn(schedulers.mainThread)
.doOnEvent { _, _ -> view?.showProgress(false) }
.subscribe({ view?.run { updateData(it) } }, { errorHandler.dispatch(it) }))
}
}

View File

@ -0,0 +1,17 @@
package io.github.wulkanowy.ui.modules.about.license
import com.mikepenz.aboutlibraries.entity.Library
import io.github.wulkanowy.ui.base.BaseView
interface LicenseView : BaseView {
val appLibraries: ArrayList<Library>?
fun initView()
fun updateData(data: List<LicenseItem>)
fun openLicense(licenseHtml: String)
fun showProgress(show: Boolean)
}

View File

@ -60,9 +60,7 @@ class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildVie
} }
override fun initView() { override fun initView() {
attendanceAdapter.apply { attendanceAdapter.setOnItemClickListener { presenter.onAttendanceItemSelected(it) }
setOnItemClickListener { presenter.onAttendanceItemSelected(it) }
}
attendanceRecycler.run { attendanceRecycler.run {
layoutManager = SmoothScrollLinearLayoutManager(context) layoutManager = SmoothScrollLinearLayoutManager(context)

View File

@ -78,6 +78,7 @@ class GradeFragment : BaseFragment(), GradeView, MainView.MainChildView, MainVie
offscreenPageLimit = 3 offscreenPageLimit = 3
setOnSelectPageListener { presenter.onPageSelected(it) } setOnSelectPageListener { presenter.onPageSelected(it) }
} }
gradeTabLayout.setupWithViewPager(gradeViewPager) gradeTabLayout.setupWithViewPager(gradeViewPager)
gradeSwipe.setOnRefreshListener { presenter.onSwipeRefresh() } gradeSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
} }

View File

@ -10,6 +10,7 @@ import io.github.wulkanowy.ui.modules.grade.details.GradeDetailsFragment
import io.github.wulkanowy.ui.modules.grade.statistics.GradeStatisticsFragment import io.github.wulkanowy.ui.modules.grade.statistics.GradeStatisticsFragment
import io.github.wulkanowy.ui.modules.grade.summary.GradeSummaryFragment import io.github.wulkanowy.ui.modules.grade.summary.GradeSummaryFragment
@Suppress("unused")
@Module @Module
abstract class GradeModule { abstract class GradeModule {

View File

@ -81,9 +81,7 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
setCenterTextColor(context.getThemeAttrColor(android.R.attr.textColorPrimary)) setCenterTextColor(context.getThemeAttrColor(android.R.attr.textColorPrimary))
animateXY(1000, 1000) animateXY(1000, 1000)
minAngleForSlices = 25f minAngleForSlices = 25f
legend.apply { legend.textColor = context.getThemeAttrColor(android.R.attr.textColorPrimary)
textColor = context.getThemeAttrColor(android.R.attr.textColorPrimary)
}
} }
context?.let { context?.let {

View File

@ -10,6 +10,7 @@ import io.github.wulkanowy.ui.modules.login.form.LoginFormFragment
import io.github.wulkanowy.ui.modules.login.studentselect.LoginStudentSelectFragment import io.github.wulkanowy.ui.modules.login.studentselect.LoginStudentSelectFragment
import io.github.wulkanowy.ui.modules.login.symbol.LoginSymbolFragment import io.github.wulkanowy.ui.modules.login.symbol.LoginSymbolFragment
@Suppress("unused")
@Module @Module
internal abstract class LoginModule { internal abstract class LoginModule {

View File

@ -17,7 +17,6 @@ import io.github.wulkanowy.ui.modules.login.LoginActivity
import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.hideSoftInput import io.github.wulkanowy.utils.hideSoftInput
import io.github.wulkanowy.utils.openInternetBrowser import io.github.wulkanowy.utils.openInternetBrowser
import io.github.wulkanowy.utils.setOnItemSelectedListener
import io.github.wulkanowy.utils.setOnTextChangedListener import io.github.wulkanowy.utils.setOnTextChangedListener
import io.github.wulkanowy.utils.showSoftInput import io.github.wulkanowy.utils.showSoftInput
import kotlinx.android.synthetic.main.fragment_login_form.* import kotlinx.android.synthetic.main.fragment_login_form.*
@ -42,7 +41,11 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
get() = loginFormPass.text.toString() get() = loginFormPass.text.toString()
override val formHostValue: String? override val formHostValue: String?
get() = resources.getStringArray(R.array.endpoints_values)[loginFormHost.selectedItemPosition] get() = hostValues.getOrNull(hostKeys.indexOf(loginFormHost.text.toString()))
private lateinit var hostKeys: Array<String>
private lateinit var hostValues: Array<String>
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_login_form, container, false) return inflater.inflate(R.layout.fragment_login_form, container, false)
@ -54,9 +57,12 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
} }
override fun initView() { override fun initView() {
hostKeys = resources.getStringArray(R.array.endpoints_keys)
hostValues = resources.getStringArray(R.array.endpoints_values)
loginFormName.setOnTextChangedListener { presenter.onNameTextChanged() } loginFormName.setOnTextChangedListener { presenter.onNameTextChanged() }
loginFormPass.setOnTextChangedListener { presenter.onPassTextChanged() } loginFormPass.setOnTextChangedListener { presenter.onPassTextChanged() }
loginFormHost.setOnItemSelectedListener { presenter.onHostSelected() } loginFormHost.setOnItemClickListener { _, _, _, _ -> presenter.onHostSelected() }
loginFormSignIn.setOnClickListener { presenter.onSignInClick() } loginFormSignIn.setOnClickListener { presenter.onSignInClick() }
loginFormPrivacyLink.setOnClickListener { presenter.onPrivacyLinkClick() } loginFormPrivacyLink.setOnClickListener { presenter.onPrivacyLinkClick() }
@ -64,13 +70,14 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
if (id == IME_ACTION_DONE || id == IME_NULL) loginFormSignIn.callOnClick() else false if (id == IME_ACTION_DONE || id == IME_NULL) loginFormSignIn.callOnClick() else false
} }
context?.let { with(loginFormHost) {
loginFormHost.adapter = ArrayAdapter.createFromResource(it, R.array.endpoints_keys, android.R.layout.simple_spinner_item) setText(hostKeys.getOrElse(0) { "" })
.apply { setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) } setAdapter(ArrayAdapter(context, R.layout.support_simple_spinner_dropdown_item, hostKeys))
keyListener = null
} }
} }
override fun setDefaultCredentials(name: String, pass: String) { override fun setCredentials(name: String, pass: String) {
loginFormName.setText(name) loginFormName.setText(name)
loginFormPass.setText(pass) loginFormPass.setText(pass)
} }
@ -143,7 +150,7 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
(activity as? LoginActivity)?.onFormFragmentAccountLogged(students, Triple( (activity as? LoginActivity)?.onFormFragmentAccountLogged(students, Triple(
loginFormName.text.toString(), loginFormName.text.toString(),
loginFormPass.text.toString(), loginFormPass.text.toString(),
resources.getStringArray(R.array.endpoints_values)[loginFormHost.selectedItemPosition] resources.getStringArray(R.array.endpoints_values)[1]
)) ))
} }

View File

@ -40,7 +40,7 @@ class LoginFormPresenter @Inject constructor(
view?.apply { view?.apply {
clearPassError() clearPassError()
clearNameError() clearNameError()
if (formHostValue?.contains("fakelog") == true) setDefaultCredentials("jan@fakelog.cf", "jan123") if (formHostValue?.contains("fakelog") == true) setCredentials("jan@fakelog.cf", "jan123")
} }
} }

View File

@ -13,7 +13,7 @@ interface LoginFormView : BaseView {
val formHostValue: String? val formHostValue: String?
fun setDefaultCredentials(name: String, pass: String) fun setCredentials(name: String, pass: String)
fun setErrorNameRequired() fun setErrorNameRequired()

View File

@ -48,7 +48,7 @@ class LoginStudentSelectItem(val student: Student) : AbstractFlexibleItem<LoginS
get() = itemView get() = itemView
init { init {
loginItemCheck.setOnClickListener { super.onClick(loginItemContainer) } loginItemCheck.keyListener = null
} }
override fun onClick(view: View?) { override fun onClick(view: View?) {

View File

@ -27,7 +27,7 @@ import io.github.wulkanowy.data.repositories.luckynumber.LuckyNumberRepository
import io.github.wulkanowy.data.repositories.semester.SemesterRepository import io.github.wulkanowy.data.repositories.semester.SemesterRepository
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView.MenuView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import io.reactivex.Maybe import io.reactivex.Maybe
import timber.log.Timber import timber.log.Timber
@ -74,8 +74,8 @@ class LuckyNumberWidgetProvider : BroadcastReceiver() {
getLuckyNumber(sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0), appWidgetId)?.luckyNumber?.toString() ?: "#" getLuckyNumber(sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0), appWidgetId)?.luckyNumber?.toString() ?: "#"
) )
setOnClickPendingIntent(R.id.luckyNumberWidgetContainer, setOnClickPendingIntent(R.id.luckyNumberWidgetContainer,
PendingIntent.getActivity(context, MenuView.LUCKY_NUMBER.id, PendingIntent.getActivity(context, MainView.Section.LUCKY_NUMBER.id,
MainActivity.getStartIntent(context, MenuView.LUCKY_NUMBER, true), FLAG_UPDATE_CURRENT)) MainActivity.getStartIntent(context, MainView.Section.LUCKY_NUMBER, true), FLAG_UPDATE_CURRENT))
}.also { }.also {
setStyles(it, intent) setStyles(it, intent)
appWidgetManager.updateAppWidget(appWidgetId, it) appWidgetManager.updateAppWidget(appWidgetId, it)

View File

@ -4,16 +4,21 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.os.Build.VERSION.SDK_INT
import android.os.Build.VERSION_CODES.LOLLIPOP
import android.os.Bundle import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import androidx.core.content.ContextCompat import androidx.core.graphics.ColorUtils
import androidx.core.view.ViewCompat
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.aurelhubert.ahbottomnavigation.AHBottomNavigation.TitleState.ALWAYS_SHOW import com.aurelhubert.ahbottomnavigation.AHBottomNavigation.TitleState.ALWAYS_SHOW
import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem
import com.google.android.material.elevation.ElevationOverlayProvider
import com.ncapdevi.fragnav.FragNavController import com.ncapdevi.fragnav.FragNavController
import com.ncapdevi.fragnav.FragNavController.Companion.HIDE import com.ncapdevi.fragnav.FragNavController.Companion.HIDE
import dagger.Lazy
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.ui.base.BaseActivity import io.github.wulkanowy.ui.base.BaseActivity
import io.github.wulkanowy.ui.modules.account.AccountDialog import io.github.wulkanowy.ui.modules.account.AccountDialog
@ -26,8 +31,9 @@ import io.github.wulkanowy.ui.modules.message.MessageFragment
import io.github.wulkanowy.ui.modules.more.MoreFragment import io.github.wulkanowy.ui.modules.more.MoreFragment
import io.github.wulkanowy.ui.modules.note.NoteFragment import io.github.wulkanowy.ui.modules.note.NoteFragment
import io.github.wulkanowy.ui.modules.timetable.TimetableFragment import io.github.wulkanowy.ui.modules.timetable.TimetableFragment
import io.github.wulkanowy.utils.dpToPx
import io.github.wulkanowy.utils.getThemeAttrColor import io.github.wulkanowy.utils.getThemeAttrColor
import io.github.wulkanowy.utils.safelyPopFragment import io.github.wulkanowy.utils.safelyPopFragments
import io.github.wulkanowy.utils.setOnViewChangeListener import io.github.wulkanowy.utils.setOnViewChangeListener
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import javax.inject.Inject import javax.inject.Inject
@ -40,10 +46,13 @@ class MainActivity : BaseActivity<MainPresenter>(), MainView {
@Inject @Inject
lateinit var navController: FragNavController lateinit var navController: FragNavController
@Inject
lateinit var overlayProvider: Lazy<ElevationOverlayProvider>
companion object { companion object {
const val EXTRA_START_MENU = "extraStartMenu" const val EXTRA_START_MENU = "extraStartMenu"
fun getStartIntent(context: Context, startMenu: MainView.MenuView? = null, clear: Boolean = false): Intent { fun getStartIntent(context: Context, startMenu: MainView.Section? = null, clear: Boolean = false): Intent {
return Intent(context, MainActivity::class.java) return Intent(context, MainActivity::class.java)
.apply { .apply {
if (clear) flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK if (clear) flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK
@ -52,24 +61,21 @@ class MainActivity : BaseActivity<MainPresenter>(), MainView {
} }
} }
override val isRootView: Boolean override val isRootView get() = navController.isRootFragment
get() = navController.isRootFragment
override val currentViewTitle: String? override val currentStackSize get() = navController.currentStack?.size
get() = (navController.currentFrag as? MainView.TitledView)?.titleStringId?.let { getString(it) }
override val currentStackSize: Int? override val currentViewTitle get() = (navController.currentFrag as? MainView.TitledView)?.titleStringId?.let { getString(it) }
get() = navController.currentStack?.size
override var startMenuIndex = 0 override var startMenuIndex = 0
override var startMenuMoreIndex = -1 override var startMenuMoreIndex = -1
private val moreMenuFragments = listOf<Fragment>( private val moreMenuFragments = mapOf<Int, Fragment>(
MessageFragment.newInstance(), MainView.Section.MESSAGE.id to MessageFragment.newInstance(),
HomeworkFragment.newInstance(), MainView.Section.HOMEWORK.id to HomeworkFragment.newInstance(),
NoteFragment.newInstance(), MainView.Section.NOTE.id to NoteFragment.newInstance(),
LuckyNumberFragment.newInstance() MainView.Section.LUCKY_NUMBER.id to LuckyNumberFragment.newInstance()
) )
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -78,11 +84,11 @@ class MainActivity : BaseActivity<MainPresenter>(), MainView {
setSupportActionBar(mainToolbar) setSupportActionBar(mainToolbar)
messageContainer = mainFragmentContainer messageContainer = mainFragmentContainer
presenter.onAttachView(this, intent.getSerializableExtra(EXTRA_START_MENU) as? MainView.MenuView) presenter.onAttachView(this, intent.getSerializableExtra(EXTRA_START_MENU) as? MainView.Section)
navController.run { with(navController) {
initialize(startMenuIndex, savedInstanceState) initialize(startMenuIndex, savedInstanceState)
pushFragment(moreMenuFragments.getOrNull(startMenuMoreIndex)) pushFragment(moreMenuFragments[startMenuMoreIndex])
} }
} }
@ -92,30 +98,31 @@ class MainActivity : BaseActivity<MainPresenter>(), MainView {
} }
override fun initView() { override fun initView() {
mainBottomNav.run { with(mainToolbar) {
addItems( if (SDK_INT >= LOLLIPOP) stateListAnimator = null
listOf( setBackgroundColor(overlayProvider.get().getSurfaceColorWithOverlayIfNeeded(dpToPx(4f)))
AHBottomNavigationItem(R.string.grade_title, R.drawable.ic_menu_main_grade_26dp, 0), }
AHBottomNavigationItem(R.string.attendance_title, R.drawable.ic_menu_main_attendance_24dp, 0),
AHBottomNavigationItem(R.string.exam_title, R.drawable.ic_menu_main_exam_24dp, 0), with(mainBottomNav) {
AHBottomNavigationItem(R.string.timetable_title, R.drawable.ic_menu_main_timetable_24dp, 0), addItems(listOf(
AHBottomNavigationItem(R.string.more_title, R.drawable.ic_menu_main_more_24dp, 0) AHBottomNavigationItem(R.string.grade_title, R.drawable.ic_main_grade, 0),
) AHBottomNavigationItem(R.string.attendance_title, R.drawable.ic_main_attendance, 0),
) AHBottomNavigationItem(R.string.exam_title, R.drawable.ic_main_exam, 0),
accentColor = ContextCompat.getColor(context, R.color.colorPrimary) AHBottomNavigationItem(R.string.timetable_title, R.drawable.ic_main_timetable, 0),
inactiveColor = getThemeAttrColor(android.R.attr.textColorSecondary) AHBottomNavigationItem(R.string.more_title, R.drawable.ic_main_more, 0)
defaultBackgroundColor = getThemeAttrColor(R.attr.bottomNavBackground) ))
accentColor = getThemeAttrColor(R.attr.colorPrimary)
inactiveColor = ColorUtils.setAlphaComponent(getThemeAttrColor(R.attr.colorOnSurface), 153)
defaultBackgroundColor = overlayProvider.get().getSurfaceColorWithOverlayIfNeeded(dpToPx(8f))
titleState = ALWAYS_SHOW titleState = ALWAYS_SHOW
currentItem = startMenuIndex currentItem = startMenuIndex
isBehaviorTranslationEnabled = false isBehaviorTranslationEnabled = false
setTitleTextSizeInSp(10f, 10f) setTitleTextSizeInSp(10f, 10f)
setOnTabSelectedListener { position, wasSelected -> setOnTabSelectedListener(presenter::onTabSelected)
presenter.onTabSelected(position, wasSelected)
}
} }
navController.run { with(navController) {
setOnViewChangeListener { presenter.onViewChange() } setOnViewChangeListener(presenter::onViewChange)
fragmentHideStrategy = HIDE fragmentHideStrategy = HIDE
rootFragments = listOf( rootFragments = listOf(
GradeFragment.newInstance(), GradeFragment.newInstance(),
@ -152,6 +159,10 @@ class MainActivity : BaseActivity<MainPresenter>(), MainView {
navController.showDialogFragment(AccountDialog.newInstance()) navController.showDialogFragment(AccountDialog.newInstance())
} }
override fun showActionBarElevation(show: Boolean) {
ViewCompat.setElevation(mainToolbar, if (show) dpToPx(4f) else 0f)
}
override fun notifyMenuViewReselected() { override fun notifyMenuViewReselected() {
(navController.currentStack?.getOrNull(0) as? MainView.MainChildView)?.onFragmentReselected() (navController.currentStack?.getOrNull(0) as? MainView.MainChildView)?.onFragmentReselected()
} }
@ -164,8 +175,8 @@ class MainActivity : BaseActivity<MainPresenter>(), MainView {
navController.pushFragment(fragment) navController.pushFragment(fragment)
} }
override fun popView() { override fun popView(depth: Int) {
navController.safelyPopFragment() navController.safelyPopFragments(depth)
} }
override fun onBackPressed() { override fun onBackPressed() {

View File

@ -1,5 +1,6 @@
package io.github.wulkanowy.ui.modules.main package io.github.wulkanowy.ui.modules.main
import com.google.android.material.elevation.ElevationOverlayProvider
import com.ncapdevi.fragnav.FragNavController import com.ncapdevi.fragnav.FragNavController
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
@ -7,7 +8,8 @@ import dagger.android.ContributesAndroidInjector
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.di.scopes.PerFragment import io.github.wulkanowy.di.scopes.PerFragment
import io.github.wulkanowy.ui.modules.about.AboutFragment import io.github.wulkanowy.ui.modules.about.AboutFragment
import io.github.wulkanowy.ui.modules.about.AboutModule import io.github.wulkanowy.ui.modules.about.license.LicenseFragment
import io.github.wulkanowy.ui.modules.about.license.LicenseModule
import io.github.wulkanowy.ui.modules.account.AccountDialog import io.github.wulkanowy.ui.modules.account.AccountDialog
import io.github.wulkanowy.ui.modules.attendance.AttendanceFragment import io.github.wulkanowy.ui.modules.attendance.AttendanceFragment
import io.github.wulkanowy.ui.modules.attendance.summary.AttendanceSummaryFragment import io.github.wulkanowy.ui.modules.attendance.summary.AttendanceSummaryFragment
@ -19,15 +21,16 @@ import io.github.wulkanowy.ui.modules.luckynumber.LuckyNumberFragment
import io.github.wulkanowy.ui.modules.message.MessageFragment import io.github.wulkanowy.ui.modules.message.MessageFragment
import io.github.wulkanowy.ui.modules.message.MessageModule import io.github.wulkanowy.ui.modules.message.MessageModule
import io.github.wulkanowy.ui.modules.message.preview.MessagePreviewFragment import io.github.wulkanowy.ui.modules.message.preview.MessagePreviewFragment
import io.github.wulkanowy.ui.modules.mobiledevice.token.MobileDeviceTokenDialog
import io.github.wulkanowy.ui.modules.mobiledevice.MobileDeviceFragment import io.github.wulkanowy.ui.modules.mobiledevice.MobileDeviceFragment
import io.github.wulkanowy.ui.modules.mobiledevice.MobileDeviceModule import io.github.wulkanowy.ui.modules.mobiledevice.MobileDeviceModule
import io.github.wulkanowy.ui.modules.mobiledevice.token.MobileDeviceTokenDialog
import io.github.wulkanowy.ui.modules.more.MoreFragment import io.github.wulkanowy.ui.modules.more.MoreFragment
import io.github.wulkanowy.ui.modules.note.NoteFragment import io.github.wulkanowy.ui.modules.note.NoteFragment
import io.github.wulkanowy.ui.modules.settings.SettingsFragment import io.github.wulkanowy.ui.modules.settings.SettingsFragment
import io.github.wulkanowy.ui.modules.timetable.TimetableFragment import io.github.wulkanowy.ui.modules.timetable.TimetableFragment
import io.github.wulkanowy.ui.modules.timetable.completed.CompletedLessonsFragment import io.github.wulkanowy.ui.modules.timetable.completed.CompletedLessonsFragment
@Suppress("unused")
@Module @Module
abstract class MainModule { abstract class MainModule {
@ -39,6 +42,11 @@ abstract class MainModule {
fun provideFragNavController(activity: MainActivity): FragNavController { fun provideFragNavController(activity: MainActivity): FragNavController {
return FragNavController(activity.supportFragmentManager, R.id.mainFragmentContainer) return FragNavController(activity.supportFragmentManager, R.id.mainFragmentContainer)
} }
//In activities must be injected as Lazy
@JvmStatic
@Provides
fun provideElevationOverlayProvider(activity: MainActivity) = ElevationOverlayProvider(activity)
} }
@PerFragment @PerFragment
@ -74,7 +82,7 @@ abstract class MainModule {
abstract fun bindTimetableFragment(): TimetableFragment abstract fun bindTimetableFragment(): TimetableFragment
@PerFragment @PerFragment
@ContributesAndroidInjector(modules = [AboutModule::class]) @ContributesAndroidInjector
abstract fun bindAboutFragment(): AboutFragment abstract fun bindAboutFragment(): AboutFragment
@PerFragment @PerFragment
@ -108,4 +116,8 @@ abstract class MainModule {
@PerFragment @PerFragment
@ContributesAndroidInjector @ContributesAndroidInjector
abstract fun bindMobileDeviceDialog(): MobileDeviceTokenDialog abstract fun bindMobileDeviceDialog(): MobileDeviceTokenDialog
@PerFragment
@ContributesAndroidInjector(modules = [LicenseModule::class])
abstract fun bindLicenseFragment(): LicenseFragment
} }

View File

@ -5,6 +5,8 @@ import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.services.sync.SyncManager import io.github.wulkanowy.services.sync.SyncManager
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.ui.modules.main.MainView.Section.GRADE
import io.github.wulkanowy.ui.modules.main.MainView.Section.MESSAGE
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import timber.log.Timber import timber.log.Timber
@ -19,7 +21,7 @@ class MainPresenter @Inject constructor(
private val analytics: FirebaseAnalyticsHelper private val analytics: FirebaseAnalyticsHelper
) : BasePresenter<MainView>(errorHandler, studentRepository, schedulers) { ) : BasePresenter<MainView>(errorHandler, studentRepository, schedulers) {
fun onAttachView(view: MainView, initMenu: MainView.MenuView?) { fun onAttachView(view: MainView, initMenu: MainView.Section?) {
super.onAttachView(view) super.onAttachView(view)
view.apply { view.apply {
getProperViewIndexes(initMenu).let { (main, more) -> getProperViewIndexes(initMenu).let { (main, more) ->
@ -34,8 +36,9 @@ class MainPresenter @Inject constructor(
analytics.logEvent("app_open", "destination" to initMenu?.name) analytics.logEvent("app_open", "destination" to initMenu?.name)
} }
fun onViewChange() { fun onViewChange(section: MainView.Section?) {
view?.apply { view?.apply {
showActionBarElevation(section != GRADE && section != MESSAGE)
currentViewTitle?.let { setViewTitle(it) } currentViewTitle?.let { setViewTitle(it) }
currentStackSize?.let { currentStackSize?.let {
if (it > 1) showHomeArrow(true) if (it > 1) showHomeArrow(true)
@ -77,10 +80,10 @@ class MainPresenter @Inject constructor(
} == true } == true
} }
private fun getProperViewIndexes(initMenu: MainView.MenuView?): Pair<Int, Int> { private fun getProperViewIndexes(initMenu: MainView.Section?): Pair<Int, Int> {
return when { return when (initMenu?.id) {
initMenu?.id in 0..3 -> initMenu!!.id to -1 in 0..3 -> initMenu!!.id to -1
(initMenu?.id ?: 0) > 3 -> 4 to initMenu!!.id - 4 in 4..10 -> 4 to initMenu!!.id
else -> prefRepository.startMenuIndex to -1 else -> prefRepository.startMenuIndex to -1
} }
} }

View File

@ -22,11 +22,13 @@ interface MainView : BaseView {
fun showAccountPicker() fun showAccountPicker()
fun showActionBarElevation(show: Boolean)
fun notifyMenuViewReselected() fun notifyMenuViewReselected()
fun setViewTitle(title: String) fun setViewTitle(title: String)
fun popView() fun popView(depth: Int = 1)
interface MainChildView { interface MainChildView {
@ -38,14 +40,17 @@ interface MainView : BaseView {
val titleStringId: Int val titleStringId: Int
} }
enum class MenuView(val id: Int) { enum class Section(val id: Int) {
GRADE(0), GRADE(0),
ATTENDANCE(1), ATTENDANCE(1),
EXAM(2), EXAM(2),
TIMETABLE(3), TIMETABLE(3),
MESSAGE(4), MORE(4),
HOMEWORK(5), MESSAGE(5),
NOTE(6), HOMEWORK(6),
LUCKY_NUMBER(7), NOTE(7),
LUCKY_NUMBER(8),
SETTINGS(9),
ABOUT(10)
} }
} }

View File

@ -8,6 +8,7 @@ import io.github.wulkanowy.di.scopes.PerFragment
import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter
import io.github.wulkanowy.ui.modules.message.tab.MessageTabFragment import io.github.wulkanowy.ui.modules.message.tab.MessageTabFragment
@Suppress("unused")
@Module @Module
abstract class MessageModule { abstract class MessageModule {

View File

@ -1,30 +0,0 @@
package io.github.wulkanowy.ui.modules.message.send
import android.graphics.drawable.Drawable
import android.net.Uri
import com.pchmn.materialchips.model.ChipInterface
import io.github.wulkanowy.data.db.entities.Recipient
class RecipientChip(var recipient: Recipient) : ChipInterface {
override fun getAvatarDrawable(): Drawable? = null
override fun getAvatarUri(): Uri? = null
override fun getId(): Any = recipient.id
override fun getLabel(): String = recipient.name
override fun getInfo(): String {
return recipient.realName.run {
substringBeforeLast("-").let { sub ->
when {
(sub == this) -> this
(sub.indexOf('(') != -1) -> indexOf("(").let { substring(if (it != -1) it else 0) }
(sub.indexOf('[') != -1) -> indexOf("[").let { substring(if (it != -1) it else 0) }
else -> substringAfter('-')
}
}.trim()
}
}
}

View File

@ -0,0 +1,14 @@
package io.github.wulkanowy.ui.modules.message.send
import io.github.wulkanowy.data.db.entities.Recipient
import io.github.wulkanowy.materialchipsinput.ChipItem
data class RecipientChipItem(
override val title: String,
override val summary: String,
val recipient: Recipient
) : ChipItem

View File

@ -2,18 +2,20 @@ package io.github.wulkanowy.ui.modules.message.send
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Rect
import android.os.Bundle import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.TouchDelegate
import android.view.View.GONE import android.view.View.GONE
import android.view.View.VISIBLE import android.view.View.VISIBLE
import android.widget.Toast import android.widget.Toast
import android.widget.Toast.LENGTH_LONG import android.widget.Toast.LENGTH_LONG
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Message import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.Recipient
import io.github.wulkanowy.data.db.entities.ReportingUnit import io.github.wulkanowy.data.db.entities.ReportingUnit
import io.github.wulkanowy.ui.base.BaseActivity import io.github.wulkanowy.ui.base.BaseActivity
import io.github.wulkanowy.utils.dpToPx
import io.github.wulkanowy.utils.hideSoftInput import io.github.wulkanowy.utils.hideSoftInput
import io.github.wulkanowy.utils.showSoftInput import io.github.wulkanowy.utils.showSoftInput
import kotlinx.android.synthetic.main.activity_send_message.* import kotlinx.android.synthetic.main.activity_send_message.*
@ -38,14 +40,18 @@ class SendMessageActivity : BaseActivity<SendMessagePresenter>(), SendMessageVie
} }
} }
override val formRecipientsData: List<Recipient> override val isDropdownListVisible: Boolean
get() = (sendMessageRecipientsInput.selectedChipList).map { (it as RecipientChip).recipient } get() = sendMessageTo.isDropdownListVisible
@Suppress("UNCHECKED_CAST")
override val formRecipientsData: List<RecipientChipItem>
get() = sendMessageTo.addedChipItems as List<RecipientChipItem>
override val formSubjectValue: String override val formSubjectValue: String
get() = sendMessageSubjectInput.text.toString() get() = sendMessageSubject.text.toString()
override val formContentValue: String override val formContentValue: String
get() = sendMessageContentInput.text.toString() get() = sendMessageMessageContent.text.toString()
override val messageRequiredRecipients: String override val messageRequiredRecipients: String
get() = getString(R.string.message_required_recipients) get() = getString(R.string.message_required_recipients)
@ -66,6 +72,12 @@ class SendMessageActivity : BaseActivity<SendMessagePresenter>(), SendMessageVie
presenter.onAttachView(this, intent.getSerializableExtra(EXTRA_MESSAGE) as? Message, intent.getSerializableExtra(EXTRA_REPLY) as? Boolean) presenter.onAttachView(this, intent.getSerializableExtra(EXTRA_MESSAGE) as? Message, intent.getSerializableExtra(EXTRA_REPLY) as? Boolean)
} }
override fun initView() {
setUpExtendedHitArea()
sendMessageScroll.setOnTouchListener { _, _ -> presenter.onTouchScroll() }
sendMessageTo.onTextChangeListener = presenter::onRecipientsTextChange
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean { override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.action_menu_send_message, menu) menuInflater.inflate(R.menu.action_menu_send_message, menu)
return true return true
@ -81,15 +93,15 @@ class SendMessageActivity : BaseActivity<SendMessagePresenter>(), SendMessageVie
} }
override fun setReportingUnit(unit: ReportingUnit) { override fun setReportingUnit(unit: ReportingUnit) {
sendMessageFromTextView.setText(unit.senderName) sendMessageFrom.text = unit.senderName
} }
override fun setRecipients(recipients: List<Recipient>) { override fun setRecipients(recipients: List<RecipientChipItem>) {
sendMessageRecipientsInput.filterableList = recipients.map { RecipientChip(it) } sendMessageTo.filterableChipItems = recipients
} }
override fun setSelectedRecipients(recipients: List<Recipient>) { override fun setSelectedRecipients(recipients: List<RecipientChipItem>) {
recipients.map { sendMessageRecipientsInput.addChip(RecipientChip(it)) } sendMessageTo.addChips(recipients)
} }
override fun showProgress(show: Boolean) { override fun showProgress(show: Boolean) {
@ -109,11 +121,11 @@ class SendMessageActivity : BaseActivity<SendMessagePresenter>(), SendMessageVie
} }
override fun setSubject(subject: String) { override fun setSubject(subject: String) {
sendMessageSubjectInput.setText(subject) sendMessageSubject.setText(subject)
} }
override fun setContent(content: String) { override fun setContent(content: String) {
sendMessageContentInput.setText(content) sendMessageMessageContent.setText(content)
} }
override fun showMessage(text: String) { override fun showMessage(text: String) {
@ -124,7 +136,41 @@ class SendMessageActivity : BaseActivity<SendMessagePresenter>(), SendMessageVie
if (show) showSoftInput() else hideSoftInput() if (show) showSoftInput() else hideSoftInput()
} }
override fun hideDropdownList() {
sendMessageTo.hideDropdownList()
}
override fun scrollToRecipients() {
sendMessageScroll.post {
sendMessageScroll.scrollTo(0, sendMessageTo.bottom - dpToPx(53f).toInt())
}
}
override fun popView() { override fun popView() {
onBackPressed() onBackPressed()
} }
private fun setUpExtendedHitArea() {
fun extendHitArea() {
val containerHitRect = Rect().apply {
sendMessageContent.getHitRect(this)
}
val contentHitRect = Rect().apply {
sendMessageMessageContent.getHitRect(this)
}
contentHitRect.top = contentHitRect.bottom
contentHitRect.bottom = containerHitRect.bottom
sendMessageContent.touchDelegate = TouchDelegate(contentHitRect, sendMessageMessageContent)
}
sendMessageMessageContent.post {
sendMessageMessageContent.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
extendHitArea()
}
extendHitArea()
}
}
} }

View File

@ -32,6 +32,7 @@ class SendMessagePresenter @Inject constructor(
fun onAttachView(view: SendMessageView, message: Message?, reply: Boolean?) { fun onAttachView(view: SendMessageView, message: Message?, reply: Boolean?) {
super.onAttachView(view) super.onAttachView(view)
view.initView()
Timber.i("Send message view was initialized") Timber.i("Send message view was initialized")
loadData(message, reply) loadData(message, reply)
view.apply { view.apply {
@ -54,15 +55,47 @@ class SendMessagePresenter @Inject constructor(
} }
} }
fun onTouchScroll(): Boolean {
return view?.run {
if (isDropdownListVisible) {
hideDropdownList()
true
} else false
} == true
}
fun onRecipientsTextChange(text: String) {
if (text.isBlank()) return
view?.scrollToRecipients()
}
fun onUpNavigate(): Boolean { fun onUpNavigate(): Boolean {
view?.popView() view?.popView()
return true return true
} }
fun onSend(): Boolean {
view?.run {
when {
formRecipientsData.isEmpty() -> showMessage(messageRequiredRecipients)
formContentValue.length < 3 -> showMessage(messageContentMinLength)
else -> {
sendMessage(
subject = formSubjectValue,
content = formContentValue,
recipients = formRecipientsData.map { it.recipient }
)
return true
}
}
}
return false
}
private fun loadData(message: Message?, reply: Boolean?) { private fun loadData(message: Message?, reply: Boolean?) {
var reportingUnit: ReportingUnit? = null var reportingUnit: ReportingUnit? = null
var recipients: List<Recipient> = emptyList() var recipientChips: List<RecipientChipItem> = emptyList()
var selectedRecipient: List<Recipient> = emptyList() var selectedRecipientChips: List<RecipientChipItem> = emptyList()
Timber.i("Loading recipients started") Timber.i("Loading recipients started")
disposable.add(studentRepository.getCurrentStudent() disposable.add(studentRepository.getCurrentStudent()
@ -73,14 +106,14 @@ class SendMessagePresenter @Inject constructor(
.flatMap { recipientRepository.getRecipients(student, 2, it).toMaybe() } .flatMap { recipientRepository.getRecipients(student, 2, it).toMaybe() }
.doOnSuccess { .doOnSuccess {
Timber.i("Loading recipients result: Success, fetched %d recipients", it.size) Timber.i("Loading recipients result: Success, fetched %d recipients", it.size)
recipients = it recipientChips = createChips(it)
} }
.flatMapCompletable { .flatMapCompletable {
if (message == null || reply != true) Completable.complete() if (message == null || reply != true) Completable.complete()
else recipientRepository.getMessageRecipients(student, message) else recipientRepository.getMessageRecipients(student, message)
.doOnSuccess { .doOnSuccess {
Timber.i("Loaded message recipients to reply result: Success, fetched %d recipients", it.size) Timber.i("Loaded message recipients to reply result: Success, fetched %d recipients", it.size)
selectedRecipient = it selectedRecipientChips = createChips(it)
} }
.ignoreElement() .ignoreElement()
} }
@ -95,11 +128,11 @@ class SendMessagePresenter @Inject constructor(
} }
.doFinally { view?.run { showProgress(false) } } .doFinally { view?.run { showProgress(false) } }
.subscribe({ .subscribe({
view?.apply { view?.run {
if (reportingUnit !== null) { if (reportingUnit !== null) {
reportingUnit?.let { setReportingUnit(it) } reportingUnit?.let { setReportingUnit(it) }
setRecipients(recipients) setRecipients(recipientChips)
if (selectedRecipient.isNotEmpty()) setSelectedRecipients(selectedRecipient) if (selectedRecipientChips.isNotEmpty()) setSelectedRecipients(selectedRecipientChips)
showContent(true) showContent(true)
} else { } else {
Timber.e("Loading recipients result: Can't find the reporting unit") Timber.e("Loading recipients result: Can't find the reporting unit")
@ -145,21 +178,29 @@ class SendMessagePresenter @Inject constructor(
) )
} }
fun onSend(): Boolean { private fun createChips(recipients: List<Recipient>): List<RecipientChipItem> {
view?.run { fun generateCorrectSummary(recipientRealName: String): String {
when { val substring = recipientRealName.substringBeforeLast("-")
formRecipientsData.isEmpty() -> showMessage(messageRequiredRecipients) return when {
formContentValue.length < 3 -> showMessage(messageContentMinLength) substring == recipientRealName -> recipientRealName
else -> { substring.indexOf("(") != -1 -> {
sendMessage( recipientRealName.indexOf("(")
subject = formSubjectValue, .let { recipientRealName.substring(if (it != -1) it else 0) }
content = formContentValue, }
recipients = formRecipientsData substring.indexOf("[") != -1 -> {
recipientRealName.indexOf("[")
.let { recipientRealName.substring(if (it != -1) it else 0) }
}
else -> recipientRealName.substringAfter("-")
}.trim()
}
return recipients.map {
RecipientChipItem(
title = it.name,
summary = generateCorrectSummary(it.realName),
recipient = it
) )
return true
} }
} }
} }
return false
}
}

View File

@ -1,12 +1,13 @@
package io.github.wulkanowy.ui.modules.message.send package io.github.wulkanowy.ui.modules.message.send
import io.github.wulkanowy.data.db.entities.Recipient
import io.github.wulkanowy.data.db.entities.ReportingUnit import io.github.wulkanowy.data.db.entities.ReportingUnit
import io.github.wulkanowy.ui.base.BaseView import io.github.wulkanowy.ui.base.BaseView
interface SendMessageView : BaseView { interface SendMessageView : BaseView {
val formRecipientsData: List<Recipient> val isDropdownListVisible: Boolean
val formRecipientsData: List<RecipientChipItem>
val formSubjectValue: String val formSubjectValue: String
@ -18,11 +19,13 @@ interface SendMessageView : BaseView {
val messageSuccess: String val messageSuccess: String
fun initView()
fun setReportingUnit(unit: ReportingUnit) fun setReportingUnit(unit: ReportingUnit)
fun setRecipients(recipients: List<Recipient>) fun setRecipients(recipients: List<RecipientChipItem>)
fun setSelectedRecipients(recipients: List<Recipient>) fun setSelectedRecipients(recipients: List<RecipientChipItem>)
fun showProgress(show: Boolean) fun showProgress(show: Boolean)
@ -38,5 +41,9 @@ interface SendMessageView : BaseView {
fun showSoftInput(show: Boolean) fun showSoftInput(show: Boolean)
fun hideDropdownList()
fun scrollToRecipients()
fun popView() fun popView()
} }

View File

@ -5,7 +5,6 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.content.ContextCompat
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
@ -20,6 +19,7 @@ import io.github.wulkanowy.ui.modules.message.MessageFragment
import io.github.wulkanowy.ui.modules.mobiledevice.MobileDeviceFragment import io.github.wulkanowy.ui.modules.mobiledevice.MobileDeviceFragment
import io.github.wulkanowy.ui.modules.note.NoteFragment import io.github.wulkanowy.ui.modules.note.NoteFragment
import io.github.wulkanowy.ui.modules.settings.SettingsFragment import io.github.wulkanowy.ui.modules.settings.SettingsFragment
import io.github.wulkanowy.utils.getCompatDrawable
import io.github.wulkanowy.utils.setOnItemClickListener import io.github.wulkanowy.utils.setOnItemClickListener
import kotlinx.android.synthetic.main.fragment_more.* import kotlinx.android.synthetic.main.fragment_more.*
import javax.inject.Inject import javax.inject.Inject
@ -39,60 +39,26 @@ class MoreFragment : BaseFragment(), MoreView, MainView.TitledView, MainView.Mai
override val titleStringId: Int override val titleStringId: Int
get() = R.string.more_title get() = R.string.more_title
override val messagesRes: Pair<String, Drawable?>? override val messagesRes: Pair<String, Drawable?>?
get() { get() = context?.run { getString(R.string.message_title) to getCompatDrawable(R.drawable.ic_more_messages) }
return context?.run {
getString(R.string.message_title) to
ContextCompat.getDrawable(this, R.drawable.ic_more_messages_24dp)
}
}
override val homeworkRes: Pair<String, Drawable?>? override val homeworkRes: Pair<String, Drawable?>?
get() { get() = context?.run { getString(R.string.homework_title) to getCompatDrawable(R.drawable.ic_more_homework) }
return context?.run {
getString(R.string.homework_title) to ContextCompat.getDrawable(this, R.drawable.ic_menu_main_homework_24dp)
}
}
override val noteRes: Pair<String, Drawable?>? override val noteRes: Pair<String, Drawable?>?
get() { get() = context?.run { getString(R.string.note_title) to getCompatDrawable(R.drawable.ic_more_note) }
return context?.run {
getString(R.string.note_title) to ContextCompat.getDrawable(this, R.drawable.ic_menu_main_note_24dp)
}
}
override val luckyNumberRes: Pair<String, Drawable?>? override val luckyNumberRes: Pair<String, Drawable?>?
get() { get() = context?.run { getString(R.string.lucky_number_title) to getCompatDrawable(R.drawable.ic_more_lucky_number) }
return context?.run {
getString(R.string.lucky_number_title) to
ContextCompat.getDrawable(this, R.drawable.ic_more_lucky_number_24dp)
}
}
override val mobileDevicesRes: Pair<String, Drawable?>? override val mobileDevicesRes: Pair<String, Drawable?>?
get() { get() = context?.run { getString(R.string.mobile_devices_title) to getCompatDrawable(R.drawable.ic_more_mobile_devices) }
return context?.run {
getString(R.string.mobile_devices_title) to
ContextCompat.getDrawable(this, R.drawable.ic_menu_main_mobile_devices_24dp)
}
}
override val settingsRes: Pair<String, Drawable?>? override val settingsRes: Pair<String, Drawable?>?
get() { get() = context?.run { getString(R.string.settings_title) to getCompatDrawable(R.drawable.ic_more_settings) }
return context?.run {
getString(R.string.settings_title) to
ContextCompat.getDrawable(this, R.drawable.ic_more_settings_24dp)
}
}
override val aboutRes: Pair<String, Drawable?>? override val aboutRes: Pair<String, Drawable?>?
get() { get() = context?.run { getString(R.string.about_title) to getCompatDrawable(R.drawable.ic_all_about) }
return context?.run {
getString(R.string.about_title) to
ContextCompat.getDrawable(this, R.drawable.ic_all_about_24dp)
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_more, container, false) return inflater.inflate(R.layout.fragment_more, container, false)
@ -104,7 +70,7 @@ class MoreFragment : BaseFragment(), MoreView, MainView.TitledView, MainView.Mai
} }
override fun initView() { override fun initView() {
moreAdapter.run { setOnItemClickListener { presenter.onItemSelected(it) } } moreAdapter.setOnItemClickListener { presenter.onItemSelected(it) }
moreRecycler.apply { moreRecycler.apply {
layoutManager = SmoothScrollLinearLayoutManager(context) layoutManager = SmoothScrollLinearLayoutManager(context)
@ -148,8 +114,8 @@ class MoreFragment : BaseFragment(), MoreView, MainView.TitledView, MainView.Mai
(activity as? MainActivity)?.pushView(AboutFragment.newInstance()) (activity as? MainActivity)?.pushView(AboutFragment.newInstance())
} }
override fun popView() { override fun popView(depth: Int) {
(activity as? MainActivity)?.popView() (activity as? MainActivity)?.popView(depth)
} }
override fun onDestroyView() { override fun onDestroyView() {

View File

@ -22,7 +22,7 @@ class MorePresenter @Inject constructor(
} }
fun onItemSelected(item: AbstractFlexibleItem<*>?) { fun onItemSelected(item: AbstractFlexibleItem<*>?) {
if (item is MoreItem) { if (item !is MoreItem) return
Timber.i("Select more item \"${item.title}\"") Timber.i("Select more item \"${item.title}\"")
view?.run { view?.run {
when (item.title) { when (item.title) {
@ -36,11 +36,10 @@ class MorePresenter @Inject constructor(
} }
} }
} }
}
fun onViewReselected() { fun onViewReselected() {
Timber.i("More view is reselected") Timber.i("More view is reselected")
view?.popView() view?.popView(2)
} }
private fun loadData() { private fun loadData() {

View File

@ -27,7 +27,7 @@ interface MoreView : BaseView {
fun openAboutView() fun openAboutView()
fun popView() fun popView(depth: Int)
fun openMessagesView() fun openMessagesView()

View File

@ -3,7 +3,8 @@ package io.github.wulkanowy.ui.modules.settings
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import com.takisoft.preferencex.PreferenceFragmentCompat import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import dagger.android.support.AndroidSupportInjection import dagger.android.support.AndroidSupportInjection
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.ui.base.BaseActivity import io.github.wulkanowy.ui.base.BaseActivity
@ -24,8 +25,7 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP
fun newInstance() = SettingsFragment() fun newInstance() = SettingsFragment()
} }
override val titleStringId: Int override val titleStringId get() = R.string.settings_title
get() = R.string.settings_title
override fun onAttach(context: Context) { override fun onAttach(context: Context) {
AndroidSupportInjection.inject(this) AndroidSupportInjection.inject(this)
@ -37,9 +37,9 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP
presenter.onAttachView(this) presenter.onAttachView(this)
} }
override fun onCreatePreferencesFix(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.scheme_preferences) setPreferencesFromResource(R.xml.scheme_preferences, rootKey)
findPreference(getString(R.string.pref_key_notification_debug)).isVisible = appInfo.isDebug findPreference<Preference>(getString(R.string.pref_key_notification_debug))?.isVisible = appInfo.isDebug
} }
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
@ -51,7 +51,7 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP
} }
override fun setServicesSuspended(serviceEnablesKey: String, isHolidays: Boolean) { override fun setServicesSuspended(serviceEnablesKey: String, isHolidays: Boolean) {
findPreference(serviceEnablesKey).run { findPreference<Preference>(serviceEnablesKey)?.apply {
summary = if (isHolidays) getString(R.string.pref_services_suspended) else "" summary = if (isHolidays) getString(R.string.pref_services_suspended) else ""
isEnabled = !isHolidays isEnabled = !isHolidays
} }

View File

@ -31,12 +31,14 @@ class SettingsPresenter @Inject constructor(
fun onSharedPreferenceChanged(key: String) { fun onSharedPreferenceChanged(key: String) {
Timber.i("Change settings $key") Timber.i("Change settings $key")
preferencesRepository.apply {
with(preferencesRepository) {
when (key) { when (key) {
serviceEnableKey -> with(syncManager) { if (isServiceEnabled) startSyncWorker() else stopSyncWorker() } serviceEnableKey -> with(syncManager) { if (isServiceEnabled) startSyncWorker() else stopSyncWorker() }
servicesIntervalKey, servicesOnlyWifiKey -> syncManager.startSyncWorker(true) servicesIntervalKey, servicesOnlyWifiKey -> syncManager.startSyncWorker(true)
isDebugNotificationEnableKey -> chuckCollector.showNotification(isDebugNotificationEnable) isDebugNotificationEnableKey -> chuckCollector.showNotification(isDebugNotificationEnable)
appThemeKey -> view?.recreateView() appThemeKey -> view?.recreateView()
else -> Unit
} }
} }
analytics.logEvent("setting_changed", "name" to key) analytics.logEvent("setting_changed", "name" to key)

View File

@ -75,7 +75,7 @@ class TimetablePresenter @Inject constructor(
fun onTimetableItemSelected(item: AbstractFlexibleItem<*>?) { fun onTimetableItemSelected(item: AbstractFlexibleItem<*>?) {
if (item is TimetableItem) { if (item is TimetableItem) {
Timber.i("Select exam item ${item.lesson.id}") Timber.i("Select timetable item ${item.lesson.id}")
view?.showTimetableDialog(item.lesson) view?.showTimetableDialog(item.lesson)
} }
} }

View File

@ -4,7 +4,6 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.content.ContextCompat
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
@ -13,6 +12,7 @@ import io.github.wulkanowy.data.db.entities.CompletedLesson
import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.getCompatDrawable
import io.github.wulkanowy.utils.setOnItemClickListener import io.github.wulkanowy.utils.setOnItemClickListener
import kotlinx.android.synthetic.main.fragment_timetable_completed.* import kotlinx.android.synthetic.main.fragment_timetable_completed.*
import javax.inject.Inject import javax.inject.Inject
@ -84,7 +84,7 @@ class CompletedLessonsFragment : BaseFragment(), CompletedLessonsView, MainView.
override fun showFeatureDisabled() { override fun showFeatureDisabled() {
context?.let { context?.let {
completedLessonsInfo.text = getString(R.string.error_feature_disabled) completedLessonsInfo.text = getString(R.string.error_feature_disabled)
completedLessonsInfoImage.setImageDrawable(ContextCompat.getDrawable(it, R.drawable.ic_all_close_circle_24dp)) completedLessonsInfoImage.setImageDrawable(it.getCompatDrawable(R.drawable.ic_all_close_circle))
} }
} }

View File

@ -20,7 +20,7 @@ import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.services.widgets.TimetableWidgetService import io.github.wulkanowy.services.widgets.TimetableWidgetService
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView.MenuView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import io.github.wulkanowy.utils.nextOrSameSchoolDay import io.github.wulkanowy.utils.nextOrSameSchoolDay
@ -130,8 +130,8 @@ class TimetableWidgetProvider : BroadcastReceiver() {
putExtra(EXTRA_FROM_PROVIDER, true) putExtra(EXTRA_FROM_PROVIDER, true)
}, FLAG_UPDATE_CURRENT)) }, FLAG_UPDATE_CURRENT))
setPendingIntentTemplate(R.id.timetableWidgetList, setPendingIntentTemplate(R.id.timetableWidgetList,
PendingIntent.getActivity(context, MenuView.TIMETABLE.id, PendingIntent.getActivity(context, MainView.Section.TIMETABLE.id,
MainActivity.getStartIntent(context, MenuView.TIMETABLE, true), FLAG_UPDATE_CURRENT)) MainActivity.getStartIntent(context, MainView.Section.TIMETABLE, true), FLAG_UPDATE_CURRENT))
}.also { }.also {
sharedPref.putLong(getDateWidgetKey(appWidgetId), date.toEpochDay(), true) sharedPref.putLong(getDateWidgetKey(appWidgetId), date.toEpochDay(), true)
appWidgetManager.apply { appWidgetManager.apply {

View File

@ -0,0 +1,31 @@
package io.github.wulkanowy.ui.widgets
import android.content.Context
import android.os.Build.VERSION_CODES.LOLLIPOP
import android.util.AttributeSet
import android.widget.LinearLayout
import androidx.annotation.RequiresApi
import androidx.core.view.ViewCompat
import com.google.android.material.shape.MaterialShapeDrawable
class MaterialLinearLayout : LinearLayout {
constructor(context: Context) : super(context)
constructor(context: Context, attr: AttributeSet) : super(context, attr)
constructor(context: Context, attr: AttributeSet, defStyleAttr: Int) : super(context, attr, defStyleAttr)
init {
val drawable = MaterialShapeDrawable.createWithElevationOverlay(context, ViewCompat.getElevation(this))
ViewCompat.setBackground(this, drawable)
}
@RequiresApi(LOLLIPOP)
override fun setElevation(elevation: Float) {
super.setElevation(elevation)
if (background is MaterialShapeDrawable) {
(background as MaterialShapeDrawable).elevation = elevation
}
}
}

View File

@ -2,9 +2,11 @@ package io.github.wulkanowy.utils
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.util.DisplayMetrics.DENSITY_DEFAULT
import androidx.annotation.AttrRes import androidx.annotation.AttrRes
import androidx.annotation.ColorInt import androidx.annotation.ColorInt
import androidx.annotation.ColorRes import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
@ColorInt @ColorInt
@ -20,9 +22,13 @@ fun Context.getThemeAttrColor(@AttrRes colorAttr: Int): Int {
@ColorInt @ColorInt
fun Context.getCompatColor(@ColorRes colorRes: Int) = ContextCompat.getColor(this, colorRes) fun Context.getCompatColor(@ColorRes colorRes: Int) = ContextCompat.getColor(this, colorRes)
fun Context.getCompatDrawable(@DrawableRes drawableRes: Int) = ContextCompat.getDrawable(this, drawableRes)
fun Context.openInternetBrowser(uri: String, onActivityNotFound: (uri: String) -> Unit) { fun Context.openInternetBrowser(uri: String, onActivityNotFound: (uri: String) -> Unit) {
Intent.parseUri(uri, 0).let { Intent.parseUri(uri, 0).let {
if (it.resolveActivity(packageManager) != null) startActivity(it) if (it.resolveActivity(packageManager) != null) startActivity(it)
else onActivityNotFound(uri) else onActivityNotFound(uri)
} }
} }
fun Context.dpToPx(dp: Float) = dp * resources.displayMetrics.densityDpi / DENSITY_DEFAULT

View File

@ -2,19 +2,20 @@ package io.github.wulkanowy.utils
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.ncapdevi.fragnav.FragNavController import com.ncapdevi.fragnav.FragNavController
import io.github.wulkanowy.ui.modules.main.MainView
inline fun FragNavController.setOnViewChangeListener(crossinline listener: (fragment: Fragment?) -> Unit) { inline fun FragNavController.setOnViewChangeListener(crossinline listener: (section: MainView.Section?) -> Unit) {
transactionListener = object : FragNavController.TransactionListener { transactionListener = object : FragNavController.TransactionListener {
override fun onFragmentTransaction(fragment: Fragment?, transactionType: FragNavController.TransactionType) { override fun onFragmentTransaction(fragment: Fragment?, transactionType: FragNavController.TransactionType) {
listener(fragment) listener(fragment?.toSection())
} }
override fun onTabTransaction(fragment: Fragment?, index: Int) { override fun onTabTransaction(fragment: Fragment?, index: Int) {
listener(fragment) listener(fragment?.toSection())
} }
} }
} }
fun FragNavController.safelyPopFragment() { fun FragNavController.safelyPopFragments(depth: Int) {
if (!isRootFragment) popFragment() if (!isRootFragment) popFragments(depth)
} }

View File

@ -0,0 +1,32 @@
package io.github.wulkanowy.utils
import androidx.fragment.app.Fragment
import io.github.wulkanowy.ui.modules.about.AboutFragment
import io.github.wulkanowy.ui.modules.attendance.AttendanceFragment
import io.github.wulkanowy.ui.modules.exam.ExamFragment
import io.github.wulkanowy.ui.modules.grade.GradeFragment
import io.github.wulkanowy.ui.modules.homework.HomeworkFragment
import io.github.wulkanowy.ui.modules.luckynumber.LuckyNumberFragment
import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.ui.modules.message.MessageFragment
import io.github.wulkanowy.ui.modules.more.MoreFragment
import io.github.wulkanowy.ui.modules.note.NoteFragment
import io.github.wulkanowy.ui.modules.settings.SettingsFragment
import io.github.wulkanowy.ui.modules.timetable.TimetableFragment
fun Fragment.toSection(): MainView.Section? {
return when (this) {
is GradeFragment -> MainView.Section.GRADE
is AttendanceFragment -> MainView.Section.ATTENDANCE
is ExamFragment -> MainView.Section.EXAM
is TimetableFragment -> MainView.Section.TIMETABLE
is MoreFragment -> MainView.Section.MORE
is MessageFragment -> MainView.Section.MESSAGE
is HomeworkFragment -> MainView.Section.HOMEWORK
is NoteFragment -> MainView.Section.NOTE
is LuckyNumberFragment -> MainView.Section.LUCKY_NUMBER
is SettingsFragment -> MainView.Section.SETTINGS
is AboutFragment -> MainView.Section.ABOUT
else -> null
}
}

View File

@ -1,16 +0,0 @@
package io.github.wulkanowy.utils
import android.view.View
import com.mikepenz.aboutlibraries.Libs
import com.mikepenz.aboutlibraries.LibsBuilder
import com.mikepenz.aboutlibraries.LibsConfiguration
inline fun LibsBuilder.withOnExtraListener(crossinline listener: (Libs.SpecialButton?) -> Unit): LibsBuilder {
withListener(object : LibsConfiguration.LibsListenerImpl() {
override fun onExtraClicked(v: View?, specialButton: Libs.SpecialButton?): Boolean {
listener(specialButton)
return true
}
})
return this
}

View File

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="28.26087"
android:viewportHeight="28.26087">
<group
android:translateX="1.1304348"
android:translateY="1.1304348">
<path
android:fillColor="#FFF"
android:pathData="M13 11h2v2h-2m0 2h2a2 2 0 0 0 2-2v-2a2 2 0 0 0-2-2h-2V7h4V5h-4a2 2 0 0 0-2 2v6c0 1.1 0.9 2 2 2m8 2H7V3h14m0-2H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2M3 5H1v16a2 2 0 0 0 2 2h16v-2H3V5z" />
</group>
</vector>

View File

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="26.086956"
android:viewportHeight="26.086956">
<group
android:translateX="1.0434783"
android:translateY="1.0434783">
<path
android:fillColor="#FFF"
android:pathData="M12,11.18C15.3,8.18 17,6.64 17,4.69C17,3.19 15.75,2 14.25,2C13.39,2 12.57,2.36 12,3C11.43,2.36 10.61,2 9.69,2C8.19,2 7,3.25 7,4.75C7,6.64 8.7,8.18 12,11.18M11.18,12C8.18,8.7 6.64,7 4.69,7C3.19,7 2,8.25 2, 9.75C2,10.61 2.36,11.43 3,12C2.36,12.57 2,13.39 2,14.31C2,15.81 3.25,17 4.75,17C6.64,17 8.18,15.3 11.18,12M12.83, 12C15.82,15.3 17.36,17 19.31,17C20.81,17 22,15.75 22,14.25C22,13.39 21.64,12.57 21,12C21.64,11.43 22,10.61 22,9.69C22, 8.19 20.75,7 19.25,7C17.36,7 15.82,8.7 12.83,12M12,12.82C8.7,15.82 7,17.36 7,19.31C7,20.81 8.25,22 9.75,22C10.61,22 11.43,21.64 12,21C12.57,21.64 13.39,22 14.31,22C15.81,22 17,20.75 17,19.25C17,17.36 15.3,15.82 12,12.82Z" />
</group>
</vector>

View File

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="26.086956"
android:viewportHeight="26.086956">
<group
android:translateX="1.0434783"
android:translateY="1.0434783">
<path
android:fillColor="#FFF"
android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM18,14L6,14v-2h12v2zM18,11L6,11L6,9h12v2zM18,8L6,8L6,6h12v2z" />
</group>
</vector>

View File

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="26.086956"
android:viewportHeight="26.086956">
<group
android:translateX="1.0434783"
android:translateY="1.0434783">
<path
android:fillColor="#FFF"
android:pathData="M20.2,2H19.5H18C17.1,2 16,3 16,4H8C8,3 6.9,2 6,2H4.5H3.8H2V11C2,12 3,13 4,13H6.2C6.6,15 7.9,16.7 11,17V19.1C8.8,19.3 8,20.4 8,21.7V22H16V21.7C16,20.4 15.2,19.3 13,19.1V17C16.1,16.7 17.4,15 17.8,13H20C21,13 22,12 22,11V2H20.2M4,11V4H6V6V11C5.1,11 4.3,11 4,11M20,11C19.7,11 18.9,11 18,11V6V4H20V11Z" />
</group>
</vector>

View File

@ -1,14 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="26.086956"
android:viewportHeight="26.086956"
android:tint="#FFFFFF">
<group
android:translateX="1.0434783"
android:translateY="1.0434783">
<path
android:fillColor="#FFFFFF"
android:pathData="M12,11.18C15.3,8.18 17,6.64 17,4.69C17,3.19 15.75,2 14.25,2C13.39,2 12.57,2.36 12,3C11.43,2.36 10.61,2 9.69,2C8.19,2 7,3.25 7,4.75C7,6.64 8.7,8.18 12,11.18M11.18,12C8.18,8.7 6.64,7 4.69,7C3.19,7 2,8.25 2,9.75C2,10.61 2.36,11.43 3,12C2.36,12.57 2,13.39 2,14.31C2,15.81 3.25,17 4.75,17C6.64,17 8.18,15.3 11.18,12M12.83,12C15.82,15.3 17.36,17 19.31,17C20.81,17 22,15.75 22,14.25C22,13.39 21.64,12.57 21,12C21.64,11.43 22,10.61 22,9.69C22,8.19 20.75,7 19.25,7C17.36,7 15.82,8.7 12.83,12M12,12.82C8.7,15.82 7,17.36 7,19.31C7,20.81 8.25,22 9.75,22C10.61,22 11.43,21.64 12,21C12.57,21.64 13.39,22 14.31,22C15.81,22 17,20.75 17,19.25C17,17.36 15.3,15.82 12,12.82Z" />
</group>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

View File

Before

Width:  |  Height:  |  Size: 473 B

After

Width:  |  Height:  |  Size: 473 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 414 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

View File

Before

Width:  |  Height:  |  Size: 343 B

After

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 302 B

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@android:color/transparent" />
<stroke
android:width="3dp"
android:color="@color/colorPrimaryLight" />
</shape>

View File

@ -5,5 +5,5 @@
android:angle="270" android:angle="270"
android:centerColor="@android:color/transparent" android:centerColor="@android:color/transparent"
android:centerX="0.01" android:centerX="0.01"
android:startColor="#494949" /> android:startColor="@color/colorDividerInverse" />
</shape> </shape>

View File

@ -1,12 +1,12 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item> <item>
<shape> <shape>
<solid android:color="#9a0007" /> <solid android:color="@color/colorPrimaryDark" />
</shape> </shape>
</item> </item>
<item <item
android:width="200dp" android:width="200dp"
android:height="200dp" android:height="200dp"
android:gravity="center" android:drawable="@drawable/img_splash_logo"
android:drawable="@drawable/img_splash_logo" /> android:gravity="center" />
</layer-list> </layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 B

View File

Before

Width:  |  Height:  |  Size: 713 B

After

Width:  |  Height:  |  Size: 713 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 449 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 268 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 554 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 B

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 590 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 624 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 401 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 801 B

Some files were not shown because too many files have changed in this diff Show More