Merge branch 'develop'

This commit is contained in:
Kuba Szczodrzyński 2020-10-17 00:22:35 +02:00
commit 0a127ac6ee
64 changed files with 765 additions and 401 deletions

View File

@ -11,6 +11,7 @@
<module name="Szkolny.eu.mhttp" target="1.8" /> <module name="Szkolny.eu.mhttp" target="1.8" />
<module name="Szkolny.eu.nachos" target="1.8" /> <module name="Szkolny.eu.nachos" target="1.8" />
<module name="Szkolny.eu.szkolny-font" target="1.8" /> <module name="Szkolny.eu.szkolny-font" target="1.8" />
<module name="Szkolny.eu.wear" target="1.8" />
</bytecodeTargetLevel> </bytecodeTargetLevel>
</component> </component>
</project> </project>

View File

@ -1,9 +1,8 @@
<h3>Wersja 4.4.2, 2020-09-05</h3> <h3>Wersja 4.4.3, 2020-10-16</h3>
<ul> <ul>
<li>Poprawione komunikaty o aktualizacjach aplikacji.</li> <li>Mobidziennik: naprawione wysyłanie wiadomości.</li>
<li>Mobidziennik: poprawione wyświetlanie przedmiotu w planie lekcji.</li> <li>Vulcan: naprawione logowanie dla dzienników w Koszalinie.</li>
<li>Mobidziennik: naprawiony moduł frekwencji.</li> <li>PPE: opcja wylogowania innych urządzeń przy logowaniu.</li>
<li>Naprawione zatrzymanie aplikacji na ekranie logowania.</li>
</ul> </ul>
<br> <br>
<br> <br>

View File

@ -9,7 +9,7 @@
/*secret password - removed for source code publication*/ /*secret password - removed for source code publication*/
static toys AES_IV[16] = { static toys AES_IV[16] = {
0x1a, 0xcd, 0xf0, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 0xaa, 0x6d, 0x87, 0x46, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat); unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat);

View File

@ -57,8 +57,8 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
val profileId val profileId
get() = profile.id get() = profile.id
var devMode = false
var debugMode = false var debugMode = false
var devMode = false
} }
val notificationChannelsManager by lazy { NotificationChannelsManager(this) } val notificationChannelsManager by lazy { NotificationChannelsManager(this) }
@ -107,7 +107,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
.readTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS)
builder.installHttpsSupport(this) builder.installHttpsSupport(this)
if (debugMode || BuildConfig.DEBUG) { if (devMode || BuildConfig.DEBUG) {
HyperLog.initialize(this) HyperLog.initialize(this)
HyperLog.setLogLevel(Log.VERBOSE) HyperLog.setLogLevel(Log.VERBOSE)
HyperLog.setLogFormat(DebugLogFormat(this)) HyperLog.setLogFormat(DebugLogFormat(this))
@ -162,7 +162,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
Iconics.registerFont(SzkolnyFont) Iconics.registerFont(SzkolnyFont)
App.db = AppDb(this) App.db = AppDb(this)
Themes.themeInt = config.ui.theme Themes.themeInt = config.ui.theme
debugMode = config.debugMode devMode = config.debugMode
MHttp.instance().customOkHttpClient(http) MHttp.instance().customOkHttpClient(http)
if (!profileLoadById(config.lastProfileId)) { if (!profileLoadById(config.lastProfileId)) {
@ -173,9 +173,9 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
setLanguage(it) setLanguage(it)
} }
devMode = BuildConfig.DEBUG debugMode = BuildConfig.DEBUG
if (BuildConfig.DEBUG) if (BuildConfig.DEBUG)
debugMode = true devMode = true
Signing.getCert(this) Signing.getCert(this)
@ -185,7 +185,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
if (config.devModePassword != null) if (config.devModePassword != null)
checkDevModePassword() checkDevModePassword()
debugMode = devMode || config.debugMode devMode = debugMode || config.debugMode
if (config.sync.enabled) if (config.sync.enabled)
SyncWorker.scheduleNext(this@App, false) SyncWorker.scheduleNext(this@App, false)

View File

@ -299,7 +299,7 @@ fun colorFromCssName(name: String): Int {
"orange" -> 0xffffa500 "orange" -> 0xffffa500
"black" -> 0xff000000 "black" -> 0xff000000
"white" -> 0xffffffff "white" -> 0xffffffff
else -> -1 else -> -1L
}.toInt() }.toInt()
} }

View File

@ -232,7 +232,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
list += NavTarget(TARGET_MESSAGES_DETAILS, R.string.menu_message, MessageFragment::class).withPopTo(DRAWER_ITEM_MESSAGES) list += NavTarget(TARGET_MESSAGES_DETAILS, R.string.menu_message, MessageFragment::class).withPopTo(DRAWER_ITEM_MESSAGES)
list += NavTarget(TARGET_MESSAGES_COMPOSE, R.string.menu_message_compose, MessagesComposeFragment::class) list += NavTarget(TARGET_MESSAGES_COMPOSE, R.string.menu_message_compose, MessagesComposeFragment::class)
list += NavTarget(TARGET_WEB_PUSH, R.string.menu_web_push, WebPushFragment::class) list += NavTarget(TARGET_WEB_PUSH, R.string.menu_web_push, WebPushFragment::class)
if (App.debugMode) { if (App.devMode) {
list += NavTarget(DRAWER_ITEM_DEBUG, R.string.menu_debug, DebugFragment::class) list += NavTarget(DRAWER_ITEM_DEBUG, R.string.menu_debug, DebugFragment::class)
list += NavTarget(TARGET_LAB, R.string.menu_lab, LabFragment::class) list += NavTarget(TARGET_LAB, R.string.menu_lab, LabFragment::class)
.withIcon(CommunityMaterial.Icon.cmd_flask_outline) .withIcon(CommunityMaterial.Icon.cmd_flask_outline)
@ -566,7 +566,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
.withIcon(CommunityMaterial.Icon2.cmd_help_circle_outline) .withIcon(CommunityMaterial.Icon2.cmd_help_circle_outline)
.withOnClickListener(View.OnClickListener { loadTarget(TARGET_FEEDBACK) }) .withOnClickListener(View.OnClickListener { loadTarget(TARGET_FEEDBACK) })
) )
if (App.debugMode) { if (App.devMode) {
bottomSheet += BottomSheetPrimaryItem(false) bottomSheet += BottomSheetPrimaryItem(false)
.withTitle(R.string.menu_debug) .withTitle(R.string.menu_debug)
.withIcon(CommunityMaterial.Icon.cmd_android_studio) .withIcon(CommunityMaterial.Icon.cmd_android_studio)

View File

@ -49,4 +49,9 @@ class ProfileConfigGrades(private val config: ProfileConfig) {
var dontCountGrades: List<String> var dontCountGrades: List<String>
get() { mDontCountGrades = mDontCountGrades ?: config.values.get("dontCountGrades", listOf()); return mDontCountGrades ?: listOf() } get() { mDontCountGrades = mDontCountGrades ?: config.values.get("dontCountGrades", listOf()); return mDontCountGrades ?: listOf() }
set(value) { config.set("dontCountGrades", value); mDontCountGrades = value } set(value) { config.set("dontCountGrades", value); mDontCountGrades = value }
private var mHideSticksFromOld: Boolean? = null
var hideSticksFromOld: Boolean
get() { mHideSticksFromOld = mHideSticksFromOld ?: config.values.get("hideSticksFromOld", false); return mHideSticksFromOld ?: false }
set(value) { config.set("hideSticksFromOld", value); mHideSticksFromOld = value }
} }

View File

@ -119,6 +119,7 @@ const val VULCAN_WEB_ENDPOINT_REGISTER_DEVICE = "RejestracjaUrzadzeniaToken.mvc/
const val EDUDZIENNIK_USER_AGENT = "Szkolny.eu/${BuildConfig.VERSION_NAME}" const val EDUDZIENNIK_USER_AGENT = "Szkolny.eu/${BuildConfig.VERSION_NAME}"
const val PODLASIE_API_VERSION = "1.0.31" const val PODLASIE_API_VERSION = "1.0.62"
const val PODLASIE_API_URL = "https://cpdklaser.zeto.bialystok.pl/api" const val PODLASIE_API_URL = "https://cpdklaser.zeto.bialystok.pl/api"
const val PODLASIE_API_USER_ENDPOINT = "/pobierzDaneUcznia" const val PODLASIE_API_USER_ENDPOINT = "/pobierzDaneUcznia"
const val PODLASIE_API_LOGOUT_DEVICES_ENDPOINT = "/wyczyscUrzadzenia"

View File

@ -12,6 +12,10 @@ object Regexes {
"""color: (\w+);?""".toRegex() """color: (\w+);?""".toRegex()
} }
val NOT_DIGITS by lazy {
"""[^0-9]""".toRegex()
}
val MOBIDZIENNIK_GRADES_SUBJECT_NAME by lazy { val MOBIDZIENNIK_GRADES_SUBJECT_NAME by lazy {

View File

@ -56,20 +56,21 @@ class MobidziennikWebGetRecipientList(override val data: DataMobidziennik,
} }
private fun processRecipient(listType: Int, listName: String, recipient: JsonObject) { private fun processRecipient(listType: Int, listName: String, recipient: JsonObject) {
val id = recipient.getLong("id") ?: -1 val id = recipient.getString("id") ?: return
val idLong = id.replace(Regexes.NOT_DIGITS, "").toLongOrNull() ?: return
// get teacher by ID or create it // get teacher by ID or create it
val teacher = data.teacherList[id] ?: Teacher(data.profileId, id).apply { val teacher = data.teacherList[idLong] ?: Teacher(data.profileId, idLong).apply {
val fullName = recipient.getString("nazwa")?.fixName() val fullName = recipient.getString("nazwa")?.fixName()
name = fullName ?: "" name = fullName ?: ""
fullName?.splitName()?.let { fullName?.splitName()?.let {
name = it.second name = it.second
surname = it.first surname = it.first
} }
data.teacherList[id] = this data.teacherList[idLong] = this
} }
teacher.apply { teacher.apply {
loginId = id.toString() loginId = id
when (listType) { when (listType) {
1 -> setTeacherType(Teacher.TYPE_PRINCIPAL) 1 -> setTeacherType(Teacher.TYPE_PRINCIPAL)
2 -> setTeacherType(Teacher.TYPE_TEACHER) 2 -> setTeacherType(Teacher.TYPE_TEACHER)

View File

@ -7,6 +7,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.firstlogin
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_PODLASIE import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_PODLASIE
import pl.szczodrzynski.edziennik.data.api.PODLASIE_API_LOGOUT_DEVICES_ENDPOINT
import pl.szczodrzynski.edziennik.data.api.PODLASIE_API_USER_ENDPOINT import pl.szczodrzynski.edziennik.data.api.PODLASIE_API_USER_ENDPOINT
import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.DataPodlasie import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.DataPodlasie
import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.data.PodlasieApi import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.data.PodlasieApi
@ -22,10 +23,23 @@ class PodlasieFirstLogin(val data: DataPodlasie, val onSuccess: () -> Unit) {
private val api = PodlasieApi(data, null) private val api = PodlasieApi(data, null)
init { init {
PodlasieLoginApi(data) {
doLogin()
}
}
private fun doLogin() {
val loginStoreId = data.loginStore.id val loginStoreId = data.loginStore.id
val loginStoreType = LOGIN_TYPE_PODLASIE val loginStoreType = LOGIN_TYPE_PODLASIE
PodlasieLoginApi(data) { if (data.loginStore.getLoginData("logoutDevices", false)) {
data.loginStore.removeLoginData("logoutDevices")
api.apiGet(TAG, PODLASIE_API_LOGOUT_DEVICES_ENDPOINT) {
doLogin()
}
return
}
api.apiGet(TAG, PODLASIE_API_USER_ENDPOINT) { json -> api.apiGet(TAG, PODLASIE_API_USER_ENDPOINT) { json ->
val uuid = json.getString("Uuid") val uuid = json.getString("Uuid")
val login = json.getString("Login") val login = json.getString("Login")
@ -67,5 +81,4 @@ class PodlasieFirstLogin(val data: DataPodlasie, val onSuccess: () -> Unit) {
onSuccess() onSuccess()
} }
} }
}
} }

View File

@ -219,6 +219,7 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
"P01" -> "http://efeb-komunikacja.pro-hudson.win.vulcan.pl" "P01" -> "http://efeb-komunikacja.pro-hudson.win.vulcan.pl"
"P02" -> "http://efeb-komunikacja.pro-hudsonrc.win.vulcan.pl" "P02" -> "http://efeb-komunikacja.pro-hudsonrc.win.vulcan.pl"
"P90" -> "http://efeb-komunikacja-pro-mwujakowska.neo.win.vulcan.pl" "P90" -> "http://efeb-komunikacja-pro-mwujakowska.neo.win.vulcan.pl"
"KO1" -> "https://uonetplus-komunikacja.eduportal.koszalin.pl"
"FK1", "FS1" -> "http://api.fakelog.cf" "FK1", "FS1" -> "http://api.fakelog.cf"
"SZ9" -> "http://hack.szkolny.eu" "SZ9" -> "http://hack.szkolny.eu"
else -> null else -> null

View File

@ -89,7 +89,7 @@ class VulcanLoginWebMain(val data: DataVulcan, val onSuccess: () -> Unit) {
return true return true
} }
val fsLogin = FSLogin(data.app.http, debug = App.debugMode) val fsLogin = FSLogin(data.app.http, debug = App.devMode)
fsLogin.performLogin( fsLogin.performLogin(
realm = realm, realm = realm,
username = data.webUsername ?: data.webEmail ?: return false, username = data.webUsername ?: data.webEmail ?: return false,

View File

@ -136,7 +136,7 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
val db: AppDb by lazy { app.db } val db: AppDb by lazy { app.db }
init { init {
if (App.devMode) { if (App.debugMode) {
fakeLogin = loginStore.hasLoginData("fakeLogin") fakeLogin = loginStore.hasLoginData("fakeLogin")
} }
clear() clear()

View File

@ -46,6 +46,6 @@ object Signing {
/*fun provideKey(param1: String, param2: Long): ByteArray {*/ /*fun provideKey(param1: String, param2: Long): ByteArray {*/
fun pleaseStopRightNow(param1: String, param2: Long): ByteArray { fun pleaseStopRightNow(param1: String, param2: Long): ByteArray {
return "$param1.MTIzNDU2Nzg5MDx45DzIF8===.$param2".sha256() return "$param1.MTIzNDU2Nzg5MDzyYb9Lof===.$param2".sha256()
} }
} }

View File

@ -193,7 +193,7 @@ class EventDetailsDialog(
b.goToTimetableButton.attachToastHint(R.string.hint_go_to_timetable) b.goToTimetableButton.attachToastHint(R.string.hint_go_to_timetable)
// RE-DOWNLOAD // RE-DOWNLOAD
b.downloadButton.isVisible = App.debugMode b.downloadButton.isVisible = App.devMode
b.downloadButton.onClick { b.downloadButton.onClick {
EdziennikTask.eventGet(event.profileId, event).enqueue(activity) EdziennikTask.eventGet(event.profileId, event).enqueue(activity)
} }

View File

@ -57,7 +57,7 @@ class GradeDetailsDialog(
b.grade = grade b.grade = grade
b.weightText = manager.getWeightString(app, grade) b.weightText = manager.getWeightString(app, grade)
b.commentVisible = false b.commentVisible = false
b.devMode = App.debugMode b.devMode = App.devMode
b.gradeName.setTextColor(if (ColorUtils.calculateLuminance(gradeColor) > 0.3) 0xaa000000.toInt() else 0xccffffff.toInt()) b.gradeName.setTextColor(if (ColorUtils.calculateLuminance(gradeColor) > 0.3) 0xaa000000.toInt() else 0xccffffff.toInt())
b.gradeName.background.setTintColor(gradeColor) b.gradeName.background.setTintColor(gradeColor)

View File

@ -78,7 +78,7 @@ class LessonDetailsDialog(
) )
} }
if (App.debugMode) if (App.devMode)
b.lessonId.visibility = View.VISIBLE b.lessonId.visibility = View.VISIBLE
update() update()

View File

@ -55,7 +55,7 @@ class AttendanceDetailsDialog(
val attendanceColor = manager.getAttendanceColor(attendance) val attendanceColor = manager.getAttendanceColor(attendance)
b.attendance = attendance b.attendance = attendance
b.devMode = App.debugMode b.devMode = App.devMode
b.attendanceName.setTextColor(if (ColorUtils.calculateLuminance(attendanceColor) > 0.3) 0xaa000000.toInt() else 0xccffffff.toInt()) b.attendanceName.setTextColor(if (ColorUtils.calculateLuminance(attendanceColor) > 0.3) 0xaa000000.toInt() else 0xccffffff.toInt())
b.attendanceName.background.setTintColor(attendanceColor) b.attendanceName.background.setTintColor(attendanceColor)

View File

@ -45,7 +45,7 @@ class ErrorDetailsDialog(
listOf( listOf(
it.getStringReason(activity).asBoldSpannable().asColoredSpannable(R.attr.colorOnBackground.resolveAttr(activity)), it.getStringReason(activity).asBoldSpannable().asColoredSpannable(R.attr.colorOnBackground.resolveAttr(activity)),
activity.getString(R.string.error_unknown_format, it.errorCode, it.tag), activity.getString(R.string.error_unknown_format, it.errorCode, it.tag),
if (App.debugMode) if (App.devMode)
it.throwable?.stackTraceString ?: it.throwable?.localizedMessage it.throwable?.stackTraceString ?: it.throwable?.localizedMessage
else else
it.throwable?.localizedMessage it.throwable?.localizedMessage

View File

@ -71,9 +71,14 @@ class GradesListFragment : Fragment(), CoroutineScope {
val adapter = GradesAdapter(activity) val adapter = GradesAdapter(activity)
var firstRun = true var firstRun = true
app.db.gradeDao().getAllOrderBy(App.profileId, app.gradesManager.getOrderByString()).observe(this@GradesListFragment, Observer { items -> this@GradesListFragment.launch { app.db.gradeDao().getAllOrderBy(App.profileId, app.gradesManager.getOrderByString()).observe(this@GradesListFragment, Observer { grades -> this@GradesListFragment.launch {
if (!isAdded) return@launch if (!isAdded) return@launch
val items = when {
app.config.forProfile().grades.hideSticksFromOld && App.devMode -> grades.filter { it.value != 1.0f }
else -> grades
}
// load & configure the adapter // load & configure the adapter
adapter.items = withContext(Dispatchers.Default) { processGrades(items) } adapter.items = withContext(Dispatchers.Default) { processGrades(items) }
if (items.isNotNullNorEmpty() && b.list.adapter == null) { if (items.isNotNullNorEmpty() && b.list.adapter == null) {

View File

@ -152,13 +152,14 @@ class HomeFragment : Fragment(), CoroutineScope {
val items = mutableListOf<HomeCard>() val items = mutableListOf<HomeCard>()
cards.mapNotNullTo(items) { cards.mapNotNullTo(items) {
@Suppress("USELESS_CAST")
when (it.cardId) { when (it.cardId) {
HomeCard.CARD_LUCKY_NUMBER -> HomeLuckyNumberCard(it.cardId, app, activity, this, app.profile) HomeCard.CARD_LUCKY_NUMBER -> HomeLuckyNumberCard(it.cardId, app, activity, this, app.profile)
HomeCard.CARD_TIMETABLE -> HomeTimetableCard(it.cardId, app, activity, this, app.profile) HomeCard.CARD_TIMETABLE -> HomeTimetableCard(it.cardId, app, activity, this, app.profile)
HomeCard.CARD_GRADES -> HomeGradesCard(it.cardId, app, activity, this, app.profile) HomeCard.CARD_GRADES -> HomeGradesCard(it.cardId, app, activity, this, app.profile)
HomeCard.CARD_EVENTS -> HomeEventsCard(it.cardId, app, activity, this, app.profile) HomeCard.CARD_EVENTS -> HomeEventsCard(it.cardId, app, activity, this, app.profile)
else -> null else -> null
} } as HomeCard?
} }
//if (App.devMode) //if (App.devMode)
// items += HomeDebugCard(100, app, activity, this, app.profile) // items += HomeDebugCard(100, app, activity, this, app.profile)

View File

@ -22,8 +22,9 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.databinding.LoginFormCheckboxItemBinding
import pl.szczodrzynski.edziennik.databinding.LoginFormFieldItemBinding
import pl.szczodrzynski.edziennik.databinding.LoginFormFragmentBinding import pl.szczodrzynski.edziennik.databinding.LoginFormFragmentBinding
import pl.szczodrzynski.edziennik.databinding.LoginFormItemBinding
import pl.szczodrzynski.navlib.colorAttr import pl.szczodrzynski.navlib.colorAttr
import java.util.* import java.util.*
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
@ -75,13 +76,14 @@ class LoginFormFragment : Fragment(), CoroutineScope {
b.subTitle.text = platformName ?: app.getString(mode.name) b.subTitle.text = platformName ?: app.getString(mode.name)
b.text.text = platformGuideText ?: app.getString(mode.guideText) b.text.text = platformGuideText ?: app.getString(mode.guideText)
val credentials = mutableMapOf<LoginInfo.Credential, LoginFormItemBinding>() val credentials = mutableMapOf<LoginInfo.BaseCredential, Any>()
for (credential in mode.credentials) { for (credential in mode.credentials) {
if (platformFormFields?.contains(credential.keyName) == false) if (platformFormFields?.contains(credential.keyName) == false)
continue continue
val b = LoginFormItemBinding.inflate(layoutInflater) if (credential is LoginInfo.FormField) {
val b = LoginFormFieldItemBinding.inflate(layoutInflater)
b.textLayout.hint = app.getString(credential.name) b.textLayout.hint = app.getString(credential.name)
if (credential.hideText) { if (credential.hideText) {
b.textEdit.inputType = InputType.TYPE_TEXT_VARIATION_PASSWORD b.textEdit.inputType = InputType.TYPE_TEXT_VARIATION_PASSWORD
@ -103,13 +105,32 @@ class LoginFormFragment : Fragment(), CoroutineScope {
this.b.formContainer.addView(b.root) this.b.formContainer.addView(b.root)
credentials[credential] = b credentials[credential] = b
} }
if (credential is LoginInfo.FormCheckbox) {
val b = LoginFormCheckboxItemBinding.inflate(layoutInflater)
b.checkbox.text = app.getString(credential.name)
b.checkbox.onChange { _, _ ->
b.errorText.text = null
}
if (arguments?.containsKey(credential.keyName) == true) {
b.checkbox.isChecked = arguments?.getBoolean(credential.keyName) == true
}
this.b.formContainer.addView(b.root)
credentials[credential] = b
}
}
activity.lastError?.let { error -> activity.lastError?.let { error ->
activity.lastError = null activity.lastError = null
startCoroutineTimer(delayMillis = 200L) { startCoroutineTimer(delayMillis = 200L) {
for (credential in credentials) { for (credential in credentials) {
credential.key.errorCodes[error.errorCode]?.let { credential.key.errorCodes[error.errorCode]?.let {
credential.value.textLayout.error = app.getString(it) (credential.value as? LoginFormFieldItemBinding)?.let { b ->
b.textLayout.error = app.getString(it)
}
(credential.value as? LoginFormCheckboxItemBinding)?.let { b ->
b.errorText.text = app.getString(it)
}
return@startCoroutineTimer return@startCoroutineTimer
} }
} }
@ -127,7 +148,7 @@ class LoginFormFragment : Fragment(), CoroutineScope {
"loginMode" to loginMode "loginMode" to loginMode
) )
if (App.devMode && b.fakeLogin.isChecked) { if (App.debugMode && b.fakeLogin.isChecked) {
payload.putBoolean("fakeLogin", true) payload.putBoolean("fakeLogin", true)
} }
@ -137,13 +158,14 @@ class LoginFormFragment : Fragment(), CoroutineScope {
var hasErrors = false var hasErrors = false
credentials.forEach { (credential, b) -> credentials.forEach { (credential, b) ->
if (credential is LoginInfo.FormField && b is LoginFormFieldItemBinding) {
var text = b.textEdit.text?.toString() ?: return@forEach var text = b.textEdit.text?.toString() ?: return@forEach
if (!credential.hideText) if (!credential.hideText)
text = text.trim() text = text.trim()
if (credential.caseMode == LoginInfo.Credential.CaseMode.UPPER_CASE) if (credential.caseMode == LoginInfo.FormField.CaseMode.UPPER_CASE)
text = text.toUpperCase(Locale.getDefault()) text = text.toUpperCase(Locale.getDefault())
if (credential.caseMode == LoginInfo.Credential.CaseMode.LOWER_CASE) if (credential.caseMode == LoginInfo.FormField.CaseMode.LOWER_CASE)
text = text.toLowerCase(Locale.getDefault()) text = text.toLowerCase(Locale.getDefault())
credential.stripTextRegex?.let { credential.stripTextRegex?.let {
@ -167,6 +189,12 @@ class LoginFormFragment : Fragment(), CoroutineScope {
payload.putString(credential.keyName, text) payload.putString(credential.keyName, text)
arguments?.putString(credential.keyName, text) arguments?.putString(credential.keyName, text)
} }
if (credential is LoginInfo.FormCheckbox && b is LoginFormCheckboxItemBinding) {
val checked = b.checkbox.isChecked
payload.putBoolean(credential.keyName, checked)
arguments?.putBoolean(credential.keyName, checked)
}
}
if (hasErrors) if (hasErrors)
return@onClick return@onClick

View File

@ -15,7 +15,7 @@ import pl.szczodrzynski.edziennik.ui.modules.grades.models.ExpandableItemModel
object LoginInfo { object LoginInfo {
private fun getEmailCredential(keyName: String) = Credential( private fun getEmailCredential(keyName: String) = FormField(
keyName = keyName, keyName = keyName,
name = R.string.login_hint_email, name = R.string.login_hint_email,
icon = CommunityMaterial.Icon.cmd_at, icon = CommunityMaterial.Icon.cmd_at,
@ -24,9 +24,9 @@ object LoginInfo {
errorCodes = mapOf(), errorCodes = mapOf(),
isRequired = true, isRequired = true,
validationRegex = "([\\w.\\-_+]+)?\\w+@[\\w-_]+(\\.\\w+)+", validationRegex = "([\\w.\\-_+]+)?\\w+@[\\w-_]+(\\.\\w+)+",
caseMode = Credential.CaseMode.LOWER_CASE caseMode = FormField.CaseMode.LOWER_CASE
) )
private fun getPasswordCredential(keyName: String) = Credential( private fun getPasswordCredential(keyName: String) = FormField(
keyName = keyName, keyName = keyName,
name = R.string.login_hint_password, name = R.string.login_hint_password,
icon = CommunityMaterial.Icon2.cmd_lock_outline, icon = CommunityMaterial.Icon2.cmd_lock_outline,
@ -94,7 +94,7 @@ object LoginInfo {
hintText = R.string.login_mode_librus_jst_hint, hintText = R.string.login_mode_librus_jst_hint,
guideText = R.string.login_mode_librus_jst_guide, guideText = R.string.login_mode_librus_jst_guide,
credentials = listOf( credentials = listOf(
Credential( FormField(
keyName = "accountCode", keyName = "accountCode",
name = R.string.login_hint_token, name = R.string.login_hint_token,
icon = CommunityMaterial.Icon.cmd_code_braces, icon = CommunityMaterial.Icon.cmd_code_braces,
@ -103,9 +103,9 @@ object LoginInfo {
errorCodes = mapOf(), errorCodes = mapOf(),
isRequired = true, isRequired = true,
validationRegex = "[A-Z0-9_]+", validationRegex = "[A-Z0-9_]+",
caseMode = Credential.CaseMode.UPPER_CASE caseMode = FormField.CaseMode.UPPER_CASE
), ),
Credential( FormField(
keyName = "accountPin", keyName = "accountPin",
name = R.string.login_hint_pin, name = R.string.login_hint_pin,
icon = CommunityMaterial.Icon2.cmd_lock, icon = CommunityMaterial.Icon2.cmd_lock,
@ -114,7 +114,7 @@ object LoginInfo {
errorCodes = mapOf(), errorCodes = mapOf(),
isRequired = true, isRequired = true,
validationRegex = "[a-z0-9_]+", validationRegex = "[a-z0-9_]+",
caseMode = Credential.CaseMode.LOWER_CASE caseMode = FormField.CaseMode.LOWER_CASE
) )
), ),
errorCodes = mapOf( errorCodes = mapOf(
@ -138,7 +138,7 @@ object LoginInfo {
guideText = R.string.login_mode_vulcan_api_guide, guideText = R.string.login_mode_vulcan_api_guide,
isRecommended = true, isRecommended = true,
credentials = listOf( credentials = listOf(
Credential( FormField(
keyName = "deviceToken", keyName = "deviceToken",
name = R.string.login_hint_token, name = R.string.login_hint_token,
icon = CommunityMaterial.Icon.cmd_code_braces, icon = CommunityMaterial.Icon.cmd_code_braces,
@ -149,9 +149,9 @@ object LoginInfo {
), ),
isRequired = true, isRequired = true,
validationRegex = "[A-Z0-9]{5,12}", validationRegex = "[A-Z0-9]{5,12}",
caseMode = Credential.CaseMode.UPPER_CASE caseMode = FormField.CaseMode.UPPER_CASE
), ),
Credential( FormField(
keyName = "symbol", keyName = "symbol",
name = R.string.login_hint_symbol, name = R.string.login_hint_symbol,
icon = CommunityMaterial.Icon2.cmd_school, icon = CommunityMaterial.Icon2.cmd_school,
@ -162,9 +162,9 @@ object LoginInfo {
), ),
isRequired = true, isRequired = true,
validationRegex = "[a-z0-9_-]+", validationRegex = "[a-z0-9_-]+",
caseMode = Credential.CaseMode.LOWER_CASE caseMode = FormField.CaseMode.LOWER_CASE
), ),
Credential( FormField(
keyName = "devicePin", keyName = "devicePin",
name = R.string.login_hint_pin, name = R.string.login_hint_pin,
icon = CommunityMaterial.Icon2.cmd_lock, icon = CommunityMaterial.Icon2.cmd_lock,
@ -175,7 +175,7 @@ object LoginInfo {
), ),
isRequired = true, isRequired = true,
validationRegex = "[0-9]+", validationRegex = "[0-9]+",
caseMode = Credential.CaseMode.LOWER_CASE caseMode = FormField.CaseMode.LOWER_CASE
) )
), ),
errorCodes = mapOf( errorCodes = mapOf(
@ -222,7 +222,7 @@ object LoginInfo {
hintText = R.string.login_mode_mobidziennik_web_hint, hintText = R.string.login_mode_mobidziennik_web_hint,
guideText = R.string.login_mode_mobidziennik_web_guide, guideText = R.string.login_mode_mobidziennik_web_guide,
credentials = listOf( credentials = listOf(
Credential( FormField(
keyName = "username", keyName = "username",
name = R.string.login_hint_login_email, name = R.string.login_hint_login_email,
icon = CommunityMaterial.Icon.cmd_account_outline, icon = CommunityMaterial.Icon.cmd_account_outline,
@ -231,9 +231,9 @@ object LoginInfo {
errorCodes = mapOf(), errorCodes = mapOf(),
isRequired = true, isRequired = true,
validationRegex = "^[a-z0-9_\\-@+.]+$", validationRegex = "^[a-z0-9_\\-@+.]+$",
caseMode = Credential.CaseMode.LOWER_CASE caseMode = FormField.CaseMode.LOWER_CASE
), ),
Credential( FormField(
keyName = "password", keyName = "password",
name = R.string.login_hint_password, name = R.string.login_hint_password,
icon = CommunityMaterial.Icon2.cmd_lock_outline, icon = CommunityMaterial.Icon2.cmd_lock_outline,
@ -246,7 +246,7 @@ object LoginInfo {
validationRegex = ".*", validationRegex = ".*",
hideText = true hideText = true
), ),
Credential( FormField(
keyName = "serverName", keyName = "serverName",
name = R.string.login_hint_address, name = R.string.login_hint_address,
icon = CommunityMaterial.Icon2.cmd_web, icon = CommunityMaterial.Icon2.cmd_web,
@ -257,7 +257,7 @@ object LoginInfo {
), ),
isRequired = true, isRequired = true,
validationRegex = "^[a-z0-9_\\-]+\$", validationRegex = "^[a-z0-9_\\-]+\$",
caseMode = Credential.CaseMode.LOWER_CASE caseMode = FormField.CaseMode.LOWER_CASE
) )
), ),
errorCodes = mapOf( errorCodes = mapOf(
@ -280,7 +280,7 @@ object LoginInfo {
hintText = R.string.login_mode_idziennik_web_hint, hintText = R.string.login_mode_idziennik_web_hint,
guideText = R.string.login_mode_idziennik_web_guide, guideText = R.string.login_mode_idziennik_web_guide,
credentials = listOf( credentials = listOf(
Credential( FormField(
keyName = "schoolName", keyName = "schoolName",
name = R.string.login_hint_school_name, name = R.string.login_hint_school_name,
icon = CommunityMaterial.Icon2.cmd_school, icon = CommunityMaterial.Icon2.cmd_school,
@ -291,9 +291,9 @@ object LoginInfo {
), ),
isRequired = true, isRequired = true,
validationRegex = "^[a-z0-9_\\-.]+$", validationRegex = "^[a-z0-9_\\-.]+$",
caseMode = Credential.CaseMode.LOWER_CASE caseMode = FormField.CaseMode.LOWER_CASE
), ),
Credential( FormField(
keyName = "username", keyName = "username",
name = R.string.login_hint_username, name = R.string.login_hint_username,
icon = CommunityMaterial.Icon.cmd_account_outline, icon = CommunityMaterial.Icon.cmd_account_outline,
@ -302,7 +302,7 @@ object LoginInfo {
errorCodes = mapOf(), errorCodes = mapOf(),
isRequired = true, isRequired = true,
validationRegex = "^[a-z0-9_\\-.]+$", validationRegex = "^[a-z0-9_\\-.]+$",
caseMode = Credential.CaseMode.LOWER_CASE caseMode = FormField.CaseMode.LOWER_CASE
), ),
getPasswordCredential("password") getPasswordCredential("password")
), ),
@ -346,7 +346,7 @@ object LoginInfo {
icon = R.drawable.login_mode_podlasie_api, icon = R.drawable.login_mode_podlasie_api,
guideText = R.string.login_mode_podlasie_api_guide, guideText = R.string.login_mode_podlasie_api_guide,
credentials = listOf( credentials = listOf(
Credential( FormField(
keyName = "apiToken", keyName = "apiToken",
name = R.string.login_hint_token, name = R.string.login_hint_token,
icon = CommunityMaterial.Icon2.cmd_lock_outline, icon = CommunityMaterial.Icon2.cmd_lock_outline,
@ -355,7 +355,15 @@ object LoginInfo {
errorCodes = mapOf(), errorCodes = mapOf(),
isRequired = true, isRequired = true,
validationRegex = "[a-zA-Z0-9]{10}", validationRegex = "[a-zA-Z0-9]{10}",
caseMode = Credential.CaseMode.UNCHANGED caseMode = FormField.CaseMode.UNCHANGED
),
FormCheckbox(
keyName = "logoutDevices",
name = R.string.login_podlasie_logout_devices,
checked = false,
errorCodes = mapOf(
ERROR_LOGIN_PODLASIE_API_DEVICE_LIMIT to R.string.error_602_reason
)
) )
), ),
errorCodes = mapOf() errorCodes = mapOf()
@ -392,7 +400,7 @@ object LoginInfo {
val isTesting: Boolean = false, val isTesting: Boolean = false,
val isPlatformSelection: Boolean = false, val isPlatformSelection: Boolean = false,
val credentials: List<Credential>, val credentials: List<BaseCredential>,
val errorCodes: Map<Int, Int> val errorCodes: Map<Int, Int>
) )
@ -409,11 +417,18 @@ object LoginInfo {
val apiData: JsonObject val apiData: JsonObject
) )
data class Credential( open class BaseCredential(
val keyName: String, open val keyName: String,
@StringRes
open val name: Int,
open val errorCodes: Map<Int, Int>
)
data class FormField(
override val keyName: String,
@StringRes @StringRes
val name: Int, override val name: Int,
val icon: IIcon, val icon: IIcon,
@StringRes @StringRes
val placeholder: Int? = null, val placeholder: Int? = null,
@ -421,7 +436,7 @@ object LoginInfo {
val emptyText: Int, val emptyText: Int,
@StringRes @StringRes
val invalidText: Int, val invalidText: Int,
val errorCodes: Map<Int, Int>, override val errorCodes: Map<Int, Int>,
@StringRes @StringRes
val hintText: Int? = null, val hintText: Int? = null,
@ -430,10 +445,18 @@ object LoginInfo {
val caseMode: CaseMode = CaseMode.UNCHANGED, val caseMode: CaseMode = CaseMode.UNCHANGED,
val hideText: Boolean = false, val hideText: Boolean = false,
val stripTextRegex: String? = null val stripTextRegex: String? = null
) { ) : BaseCredential(keyName, name, errorCodes) {
enum class CaseMode { UNCHANGED, UPPER_CASE, LOWER_CASE } enum class CaseMode { UNCHANGED, UPPER_CASE, LOWER_CASE }
} }
data class FormCheckbox(
override val keyName: String,
@StringRes
override val name: Int,
val checked: Boolean = false,
override val errorCodes: Map<Int, Int> = mapOf()
) : BaseCredential(keyName, name, errorCodes)
var chooserList: MutableList<Any>? = null var chooserList: MutableList<Any>? = null
var platformList: MutableMap<Int, List<Platform>> = mutableMapOf() var platformList: MutableMap<Int, List<Platform>> = mutableMapOf()
} }

View File

@ -108,7 +108,7 @@ class MessageFragment : Fragment(), CoroutineScope {
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)
.show() .show()
} }
b.downloadButton.isVisible = App.debugMode b.downloadButton.isVisible = App.devMode
b.downloadButton.onClick { b.downloadButton.onClick {
EdziennikTask.messageGet(App.profileId, message).enqueue(activity) EdziennikTask.messageGet(App.profileId, message).enqueue(activity)
} }

View File

@ -581,7 +581,7 @@ public class SettingsNewFragment extends MaterialAboutFragment {
syncCardIntervalItem.setChecked(app.getConfig().getSync().getEnabled()); syncCardIntervalItem.setChecked(app.getConfig().getSync().getEnabled());
syncCardIntervalItem.setOnClickAction(() -> { syncCardIntervalItem.setOnClickAction(() -> {
List<CharSequence> intervalNames = new ArrayList<>(); List<CharSequence> intervalNames = new ArrayList<>();
if (App.Companion.getDevMode() && false) { if (App.Companion.getDebugMode() && false) {
intervalNames.add(ExtensionsKt.plural(activity, R.plurals.time_till_seconds, 30)); intervalNames.add(ExtensionsKt.plural(activity, R.plurals.time_till_seconds, 30));
intervalNames.add(ExtensionsKt.plural(activity, R.plurals.time_till_minutes, 2)); intervalNames.add(ExtensionsKt.plural(activity, R.plurals.time_till_minutes, 2));
} }
@ -593,7 +593,7 @@ public class SettingsNewFragment extends MaterialAboutFragment {
intervalNames.add(ExtensionsKt.plural(activity, R.plurals.time_till_hours, 3)); intervalNames.add(ExtensionsKt.plural(activity, R.plurals.time_till_hours, 3));
intervalNames.add(ExtensionsKt.plural(activity, R.plurals.time_till_hours, 4)); intervalNames.add(ExtensionsKt.plural(activity, R.plurals.time_till_hours, 4));
List<Integer> intervals = new ArrayList<>(); List<Integer> intervals = new ArrayList<>();
if (App.Companion.getDevMode() && false) { if (App.Companion.getDebugMode() && false) {
intervals.add(30); intervals.add(30);
intervals.add(2 * 60); intervals.add(2 * 60);
} }
@ -1059,6 +1059,24 @@ public class SettingsNewFragment extends MaterialAboutFragment {
); );
} }
if (App.Companion.getDevMode()) {
items.add(
new MaterialAboutSwitchItem(
getString(R.string.settings_register_hide_sticks_from_old),
null,
new IconicsDrawable(activity)
.icon(CommunityMaterial.Icon2.cmd_numeric_1_box_outline)
.size(IconicsSize.dp(iconSizeDp))
.color(IconicsColor.colorInt(iconColor))
)
.setChecked(app.getConfig().forProfile().getGrades().getHideSticksFromOld())
.setOnChangeAction((isChecked, tag) -> {
app.getConfig().forProfile().getGrades().setHideSticksFromOld(isChecked);
return true;
})
);
}
} }
return items; return items;
} }
@ -1245,7 +1263,7 @@ public class SettingsNewFragment extends MaterialAboutFragment {
}) })
.build());*/ .build());*/
if (App.Companion.getDebugMode()) { if (App.Companion.getDevMode()) {
items.add(new MaterialAboutActionItem.Builder() items.add(new MaterialAboutActionItem.Builder()
.text(R.string.settings_about_crash_text) .text(R.string.settings_about_crash_text)
.subText(R.string.settings_about_crash_subtext) .subText(R.string.settings_about_crash_subtext)

View File

@ -108,7 +108,7 @@ public class Utils {
public static List<String> debugLog = new ArrayList<>(); public static List<String> debugLog = new ArrayList<>();
public static void d(String TAG, String message) { public static void d(String TAG, String message) {
if (App.Companion.getDebugMode()) { if (App.Companion.getDevMode()) {
HyperLog.d("Szkolny/"+TAG, message); HyperLog.d("Szkolny/"+TAG, message);
//debugLog.add(TAG+": "+message); //debugLog.add(TAG+": "+message);
} }

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) Kuba Szczodrzyński 2020-10-16.
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingVertical="4dp">
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/checkbox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="0dp"
tools:text="Text" />
<TextView
android:id="@+id/errorText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="32dp"
android:textColor="?colorError"
tools:text="Error text" />
</LinearLayout>
</layout>

View File

@ -1233,4 +1233,5 @@
<string name="permissions_attachment">In order to download the file, you have to grant file storage permission for the application.\n\nClick OK to grant the permission.</string> <string name="permissions_attachment">In order to download the file, you have to grant file storage permission for the application.\n\nClick OK to grant the permission.</string>
<string name="permissions_denied">You denied the required permissions for the application.\n\nIn order to grant the permission, open the Permissions screen for Szkolny.eu in phone settings.\n\nClick OK to open app settings now.</string> <string name="permissions_denied">You denied the required permissions for the application.\n\nIn order to grant the permission, open the Permissions screen for Szkolny.eu in phone settings.\n\nClick OK to open app settings now.</string>
<string name="permissions_required">Required permissions</string> <string name="permissions_required">Required permissions</string>
<string name="settings_register_hide_sticks_from_old">Your mother won\'t see your F grades</string>
</resources> </resources>

View File

@ -1378,4 +1378,6 @@
<string name="home_availability_info">Zobacz więcej</string> <string name="home_availability_info">Zobacz więcej</string>
<string name="home_availability_update">Aktualizuj</string> <string name="home_availability_update">Aktualizuj</string>
<string name="register_unavailable_read_more">Dowiedz się więcej</string> <string name="register_unavailable_read_more">Dowiedz się więcej</string>
<string name="settings_register_hide_sticks_from_old">Stara nie zobaczy pał</string>
<string name="login_podlasie_logout_devices">Wyloguj z pozostałych urządzeń</string>
</resources> </resources>

View File

@ -5,8 +5,8 @@ buildscript {
kotlin_version = '1.3.61' kotlin_version = '1.3.61'
release = [ release = [
versionName: "4.4.2", versionName: "4.4.3",
versionCode: 4040299 versionCode: 4040399
] ]
setup = [ setup = [
@ -53,6 +53,8 @@ buildscript {
retrofit : "2.6.4" retrofit : "2.6.4"
] ]
versions.kotlin = '1.4.0'
versions.kotlin = '1.4.0'
} }
repositories { repositories {

View File

@ -1,3 +1,5 @@
include ':wear'
include ':wear'
include ':codegen' include ':codegen'
include ':annotation' include ':annotation'
rootProject.name='Szkolny.eu' rootProject.name='Szkolny.eu'

1
wear/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

View File

@ -1,37 +1,53 @@
apply plugin: 'com.android.application' /*
* Copyright (c) Kacper Ziubryniewicz 2020-9-17
*/
plugins {
id 'com.android.application'
id 'kotlin-android'
}
android { android {
compileSdkVersion 28 compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig { defaultConfig {
applicationId "pl.szczodrzynski.edziennik" applicationId "pl.szczodrzynski.edziennik"
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 28 targetSdkVersion 29
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
buildTypes { buildTypes {
release { release {
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
} }
compileOptions { compileOptions {
sourceCompatibility = '1.8' sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility = '1.8' targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
} }
} }
dependencies { dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib:${versions.kotlin}"
implementation 'androidx.core:core-ktx:1.3.1'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation 'com.google.android.support:wearable:2.4.0' implementation 'androidx.wear:wear:1.0.0'
implementation 'com.google.android.gms:play-services-wearable:16.0.1' implementation 'com.google.android.support:wearable:2.7.0'
implementation 'androidx.percentlayout:percentlayout:1.0.0-beta01' compileOnly 'com.google.android.wearable:wearable:2.7.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0-beta01'
implementation 'androidx.recyclerview:recyclerview:1.0.0-beta01' implementation "com.google.android.gms:play-services-wearable:${versions.play_services}"
implementation 'androidx.wear:wear:1.0.0-beta01'
compileOnly 'com.google.android.wearable:wearable:2.4.0'
} }

21
wear/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2020-9-17
*/
package pl.szczodrzynski.edziennik
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("pl.szczodrzynski.edziennik", appContext.packageName)
}
}

View File

@ -1,44 +1,43 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) Kacper Ziubryniewicz 2020-9-17
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="pl.szczodrzynski.edziennik"> package="pl.szczodrzynski.edziennik">
<uses-feature android:name="android.hardware.type.watch" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- Required to act as a custom watch face. --> <uses-feature android:name="android.hardware.type.watch" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <!-- Required for complications to receive complication data and open the provider chooser. -->
<uses-permission android:name="com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA" />
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@android:style/Theme.DeviceDefault"> android:theme="@style/Theme.Szkolnyeu">
<meta-data
android:name="com.google.android.wearable.standalone"
android:value="false" />
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<uses-library <uses-library
android:name="com.google.android.wearable" android:name="com.google.android.wearable"
android:required="true" /> android:required="true" />
<!--
Set to true if your app is Standalone, that is, it does not require the handheld
app to run.
-->
<meta-data
android:name="com.google.android.wearable.standalone"
android:value="true" />
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:label="@string/app_name" android:label="@string/app_name">
android:theme="@style/AppThemeDark">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name="android.support.wearable.activity.ConfirmationActivity">
</activity>
</application> </application>
</manifest> </manifest>

View File

@ -1,153 +0,0 @@
package pl.szczodrzynski.edziennik;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import androidx.wear.widget.drawer.WearableDrawerLayout;
import androidx.wear.widget.drawer.WearableDrawerView;
import androidx.wear.widget.drawer.WearableNavigationDrawerView;
import android.support.wearable.activity.WearableActivity;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.wearable.CapabilityClient;
import com.google.android.gms.wearable.CapabilityInfo;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataItem;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.PutDataMapRequest;
import com.google.android.gms.wearable.PutDataRequest;
import com.google.android.gms.wearable.Wearable;
import java.util.Arrays;
import java.util.Set;
public class MainActivity extends WearableActivity {
private static final String TAG = "MainActivity";
private ProgressBar progressBar;
private WearableDrawerLayout wearableDrawerLayout;
private WearableNavigationDrawerView mWearableNavigationDrawer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Enables Always-on
setAmbientEnabled();
progressBar = findViewById(R.id.progressBar);
wearableDrawerLayout = findViewById(R.id.drawer_layout);
wearableDrawerLayout.setDrawerStateCallback(new WearableDrawerLayout.DrawerStateCallback() {
@Override
public void onDrawerOpened(WearableDrawerLayout layout, WearableDrawerView drawerView) {
super.onDrawerOpened(layout, drawerView);
}
@Override
public void onDrawerClosed(WearableDrawerLayout layout, WearableDrawerView drawerView) {
super.onDrawerClosed(layout, drawerView);
progressBar.setVisibility(View.GONE);
}
});
mWearableNavigationDrawer = (WearableNavigationDrawerView) findViewById(R.id.top_navigation_drawer);
WearableNavigationDrawerView.WearableNavigationDrawerAdapter navigationDrawerAdapter = new NavigationDrawerAdapter(this);
mWearableNavigationDrawer.setAdapter(navigationDrawerAdapter);
mWearableNavigationDrawer.addOnItemSelectedListener(new WearableNavigationDrawerView.OnItemSelectedListener() {
@Override
public void onItemSelected(int i) {
//Toast.makeText(MainActivity.this, "Selected item "+i, Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.VISIBLE);
}
});
// Peeks navigation drawer on the top.
mWearableNavigationDrawer.getController().peekDrawer();
Wearable.getMessageClient(this).addListener(messageEvent -> {
Log.d(TAG, messageEvent.getPath()+" :: "+ Arrays.toString(messageEvent.getData()));
});
Task<CapabilityInfo> capabilityInfoTask =
Wearable.getCapabilityClient(this)
.getCapability("edziennik_phone_app", CapabilityClient.FILTER_REACHABLE);
capabilityInfoTask.addOnCompleteListener((task) -> {
if (task.isSuccessful()) {
CapabilityInfo capabilityInfo = task.getResult();
assert capabilityInfo != null;
Set<Node> nodes;
nodes = capabilityInfo.getNodes();
Log.d(TAG, "Nodes "+nodes);
} else {
Log.d(TAG, "Capability request failed to return any results.");
}
});
Wearable.getDataClient(this).addListener(dataEventBuffer -> {
Log.d(TAG, "onDataChanged(): " + dataEventBuffer);
for (DataEvent event : dataEventBuffer) {
if (event.getType() == DataEvent.TYPE_CHANGED) {
String path = event.getDataItem().getUri().getPath();
Log.d(TAG, "Data "+path+ " :: "+Arrays.toString(event.getDataItem().getData()));
}
}
});
findViewById(R.id.test).setOnClickListener((v -> {
PutDataMapRequest putDataMapRequest = PutDataMapRequest.create("/ping");
putDataMapRequest.getDataMap().putLong("millis", System.currentTimeMillis());
PutDataRequest request = putDataMapRequest.asPutDataRequest();
request.setData("Hello".getBytes());
request.setUrgent();
Log.d(TAG, "Generating DataItem: " + request);
Task<DataItem> dataItemTask =
Wearable.getDataClient(getApplicationContext()).putDataItem(request);
dataItemTask.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
Log.d(TAG, "success");
} else {
Log.d(TAG, "Capability request failed to return any results.");
}
});
}));
// Block on a task and get the result synchronously (because this is on a background
// thread).
//DataItem dataItem = dataItemTask.getResult();
//Log.d(TAG, "DataItem saved: " + dataItem);
}
private class NavigationDrawerAdapter extends WearableNavigationDrawerView.WearableNavigationDrawerAdapter {
public NavigationDrawerAdapter(Activity activity) {
}
@Override
public CharSequence getItemText(int i) {
return "Item "+i;
}
@Override
public Drawable getItemDrawable(int i) {
return null;
}
@Override
public int getCount() {
return 5;
}
}
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2020-9-17
*/
package pl.szczodrzynski.edziennik
import android.os.Bundle
import android.support.wearable.activity.WearableActivity
import com.google.android.gms.wearable.*
class MainActivity : WearableActivity(), DataClient.OnDataChangedListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Enables Always-on
setAmbientEnabled()
}
override fun onDataChanged(dataEvents: DataEventBuffer) {
dataEvents.forEach { event ->
if (event.type == DataEvent.TYPE_CHANGED) {
event.dataItem.also { item ->
if (item?.uri?.path?.compareTo("/test") == 0) {
DataMapItem.fromDataItem(item).dataMap.apply {
getInt("test")
}
}
}
} else if (event.type == DataEvent.TYPE_DELETED) {
// DataItem deleted
}
}
}
override fun onResume() {
super.onResume()
Wearable.getDataClient(this).addListener(this)
}
override fun onPause() {
super.onPause()
Wearable.getDataClient(this).removeListener(this)
}
}

View File

@ -0,0 +1,34 @@
<!--
~ Copyright (c) Kacper Ziubryniewicz 2020-9-17
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

View File

@ -0,0 +1,174 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) Kacper Ziubryniewicz 2020-9-17
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

View File

@ -1,47 +1,29 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?><!--
<androidx.wear.widget.drawer.WearableDrawerLayout ~ Copyright (c) Kacper Ziubryniewicz 2020-9-17
xmlns:android="http://schemas.android.com/apk/res/android" -->
<androidx.wear.widget.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:background="@color/white"
android:padding="@dimen/box_inset_layout_padding"
tools:context=".MainActivity"
tools:deviceIds="wear">
<FrameLayout <FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:id="@+id/content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:nestedScrollingEnabled="true"> android:padding="@dimen/inner_frame_layout_padding"
app:boxedEdges="all"
tools:ignore="MissingPrefix">
<LinearLayout <TextView
android:id="@+id/linear_layout" android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="@+id/test"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Send"/> android:text="@string/hello_world" />
</LinearLayout>
</ScrollView>
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</FrameLayout> </FrameLayout>
</androidx.wear.widget.BoxInsetLayout>
<androidx.wear.widget.drawer.WearableNavigationDrawerView
android:id="@+id/top_navigation_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary"
app:navigationStyle="multiPage"/>
</androidx.wear.widget.drawer.WearableDrawerLayout>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) Kacper Ziubryniewicz 2020-9-17
-->
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) Kacper Ziubryniewicz 2020-9-17
-->
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,20 @@
<!--
~ Copyright (c) Kacper Ziubryniewicz 2020-9-17
-->
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Szkolnyeu" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryDark">@color/purple_700</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

View File

@ -1,3 +1,7 @@
<!--
~ Copyright (c) Kacper Ziubryniewicz 2020-9-17
-->
<resources> <resources>
<string name="hello_world">Hello Round World!</string> <string name="hello_world">Hello Round World!</string>
</resources> </resources>

View File

@ -1,9 +1,14 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) Kacper Ziubryniewicz 2020-9-17
-->
<resources> <resources>
<color name="colorPrimary">#2196F3</color> <color name="purple_200">#FFBB86FC</color>
<color name="colorPrimaryDark">#1976D2</color> <color name="purple_500">#FF6200EE</color>
<color name="colorAccent">#FF5722</color> <color name="purple_700">#FF3700B3</color>
<color name="colorSection">#4CAF50</color> <color name="teal_200">#FF03DAC5</color>
<color name="background">#000000</color> <color name="teal_700">#FF018786</color>
<color name="digital_text">#ffffff</color> <color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources> </resources>

View File

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) Kacper Ziubryniewicz 2020-9-17
-->
<resources> <resources>
<!-- <!--
Because the window insets on round devices are larger than 15dp, this padding only applies Because the window insets on round devices are larger than 15dp, this padding only applies

View File

@ -1,3 +1,7 @@
<!--
~ Copyright (c) Kacper Ziubryniewicz 2020-9-17
-->
<resources> <resources>
<string name="app_name">Szkolny.eu</string> <string name="app_name">Szkolny.eu</string>
<!-- <!--

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppThemeDark" parent="android:Theme.Material.NoActionBar" >
<item name="android:colorPrimary">@color/colorPrimary</item>
<item name="android:colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="android:colorAccent">@color/colorAccent</item>
</style>
</resources>

View File

@ -0,0 +1,20 @@
<!--
~ Copyright (c) Kacper Ziubryniewicz 2020-9-17
-->
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Szkolnyeu" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryDark">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="android_wear_capabilities">
<item>edziennik_wear_app</item>
</string-array>
</resources>

View File

@ -0,0 +1,20 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2020-9-17
*/
package pl.szczodrzynski.edziennik
import org.junit.Assert.assertEquals
import org.junit.Test
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}