Compare commits

..

3 Commits

48 changed files with 1013 additions and 987 deletions

View File

@ -1,6 +1,7 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'io.fabric'
@ -91,7 +92,7 @@ tasks.whenTaskAdded { task ->
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
annotationProcessor "androidx.room:room-compiler:${versions.room}"
kapt "androidx.room:room-compiler:${versions.room}"
debugImplementation "com.amitshekhar.android:debug-db:1.0.5"
implementation "android.arch.navigation:navigation-fragment-ktx:${versions.navigationFragment}"
@ -159,11 +160,16 @@ dependencies {
//implementation 'com.github.wulkanowy:uonet-request-signer:master-SNAPSHOT'
//implementation 'com.github.kuba2k2.uonet-request-signer:android:master-63f094b14a-1'
//implementation "org.redundent:kotlin-xml-builder:1.5.3"
implementation "org.redundent:kotlin-xml-builder:1.5.3"
implementation "io.github.wulkanowy:signer-android:0.1.1"
implementation "androidx.work:work-runtime-ktx:${versions.work}"
api "com.google.dagger:dagger:${versions.dagger}"
api "com.google.dagger:dagger-android-support:${versions.dagger}"
kapt "com.google.dagger:dagger-compiler:${versions.dagger}"
kapt "com.google.dagger:dagger-android-processor:${versions.dagger}"
}
repositories {
mavenCentral()

View File

@ -15,14 +15,10 @@
android:theme="@style/SplashTheme"
android:usesCleartextTraffic="true"
tools:ignore="UnusedAttribute">
<activity
android:name=".ui.modules.login.LoginLibrusCaptchaActivity"
android:theme="@android:style/Theme.Dialog"
android:excludeFromRecents="true"/>
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:configChanges="orientation|screenSize"
android:launchMode="singleTop"
android:theme="@style/SplashTheme">
<intent-filter>
@ -33,7 +29,7 @@
</intent-filter>
</activity>
<activity
android:name=".ui.modules.messages.MessagesComposeActivity"
android:name="pl.szczodrzynski.edziennik.ui.modules.messages.MessagesComposeActivity"
android:configChanges="orientation|screenSize"
android:label="@string/messages_compose_title"
android:theme="@style/AppTheme.Black" />
@ -43,7 +39,7 @@
android:label="@string/app_name"
android:theme="@style/AppTheme" />
<activity
android:name=".ui.modules.login.LoginActivity"
android:name="pl.szczodrzynski.edziennik.ui.modules.login.LoginActivity"
android:configChanges="orientation|screenSize"
android:launchMode="singleTop"
android:theme="@style/AppTheme.Light" />
@ -105,18 +101,22 @@
android:excludeFromRecents="true"
android:noHistory="true"
android:theme="@style/AppTheme.NoDisplay" />
<activity
android:name=".ui.modules.settings.SettingsLicenseActivity"
android:configChanges="orientation|keyboardHidden"
android:theme="@style/AppTheme" />
<activity
android:name="com.theartofdev.edmodo.cropper.CropImageActivity"
android:configChanges="orientation|keyboardHidden"
android:theme="@style/Base.Theme.AppCompat" />
<activity
android:name=".ui.modules.webpush.WebPushConfigActivity"
android:configChanges="orientation|keyboardHidden"
android:theme="@style/AppTheme.Dark" />
<activity
android:name=".ui.modules.home.CounterActivity"
android:theme="@style/AppTheme.Black" />
@ -169,6 +169,7 @@
android:name="android.appwidget.provider"
android:resource="@xml/widget_notifications_info" />
</receiver>
<receiver
android:name=".widgets.luckynumber.WidgetLuckyNumber"
android:label="@string/widget_lucky_number_title">
@ -187,6 +188,7 @@
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
<receiver android:name=".receivers.BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
@ -194,24 +196,6 @@
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<receiver
android:name=".sync.FirebaseBroadcastReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</receiver>
<receiver
android:name=".receivers.SzkolnyReceiver"
android:exported="true">
<intent-filter>
<action android:name="pl.szczodrzynski.edziennik.SZKOLNY_MAIN" />
</intent-filter>
</receiver>
<service
android:name=".sync.MyFirebaseMessagingService"
android:exported="false">
@ -220,6 +204,14 @@
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<receiver
android:name=".sync.FirebaseBroadcastReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</receiver>
<service
android:name=".widgets.timetable.WidgetTimetableService"
android:permission="android.permission.BIND_REMOTEVIEWS" />
@ -230,6 +222,14 @@
<service android:name=".Notifier$GetDataRetryService" />
<receiver
android:name=".receivers.SzkolnyReceiver"
android:exported="true">
<intent-filter>
<action android:name="pl.szczodrzynski.edziennik.SZKOLNY_MAIN" />
</intent-filter>
</receiver>
<service android:name=".api.v2.ApiService" />
</application>
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
@ -244,4 +244,4 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
</manifest>
</manifest>

View File

@ -31,11 +31,57 @@
</head>
<body>
<h3>Wersja 4.0, 2019-jeszcze-nie-wiem-kiedy</h3>
<h3>Wersja 3.1.1, 2019-10-09</h3>
<ul>
<li>UWAGA. To jest wersja in-development. Wiele funkcji może nie działać prawidłowo (lub wcale), co oznacza tylko że nie zostały jeszcze przeniesione
z wersji 3.x. Proszę o cierpliwość oraz <b>nie udostępnianie</b> tej wersji <u>nikomu</u>.</li>
<li>Bardzo dużo zmian</li>
<li>Librus: poprawiona synchronizacja kategorii i kolorów ocen.</li>
<li>Zmieniony kolor dolnego paska w ciemnym motywie.</li>
<li>Zaktualizowany licznik czasu lekcji.</li>
</ul>
<h3>Wersja 3.1, 2019-09-29</h3>
<ul>
<li>Poprawiony interfejs zadań domowych.</li>
<li>Librus: wyświetlanie komentarzy ocen.</li>
<li>Librus: wyświetlanie nieobecności nauczycieli w Terminarzu.</li>
<li>Librus: usprawniona synchronizacja ocen.</li>
<li>Poprawki angielskiego tłumaczenia.</li>
</ul>
<h3>Wersja 3.0.3, 2019-09-26</h3>
<ul>
<li>Librus: poprawka kilku błędów synchronizacji.</li>
<li>Vulcan: prawidłowe oznaczanie wiadomości jako przeczytana.</li>
<li>Vulcan: poprawiona synchronizacja wiadomości i frekwencji.</li>
<li>Vulcan: poprawka błędów logowania.</li>
</ul>
<h3>Wersja 3.0.2, 2019-09-24</h3>
<ul>
<li>Librus: pobieranie Bieżących ocen opisowych.</li>
<li>Poprawki UI: kolor ikon paska statusu w jasnym motywie.</li>
<li>Poprawka braku skanera QR do przekazywania powiadomień.</li>
<li>Poprawka wyboru koloru i daty własnego wydarzenia, które crashowały aplikację.</li>
</ul>
<h3>Wersja 3.0.1, 2019-09-19</h3>
<ul>
<li>Librus: Poprawa błędu synchronizacji.</li>
<li>Poprawki UI związane z paskiem nawigacji.</li>
<li>Mobidziennik: Pobieranie ocen w niektórych przedmiotach.</li>
</ul>
<h3>Wersja 3.0, 2019-09-13</h3>
<ul>
<li><b>Nowy wygląd i sposób nawigacji</b> w całej aplikacji.</li>
<li>Menu nawigacji można teraz otworzyć przyciskiem na <b>dolnym pasku</b>. Pociągnięcie w górę tego paska wyświetla <b>menu kontekstowe</b> dotyczące danego widoku.</li>
<li>Założyliśmy serwer Discord! <a href="https://discord.gg/n9e8pWr">https://discord.gg/n9e8pWr</a></li>
<br>
<li>Librus: poprawka powielonych ogłoszeń szkolnych.</li>
<li>Naprawiłem błąd nieskończonej synchronizacji w Vulcanie.</li>
<li>Naprawiłem crash launchera przy dodaniu widgetu.</li>
<li>Naprawiłem częste crashe związane z widokiem kalendarza.</li>
<li>Nowe, ładniejsze (choć trochę) motywy kolorów.</li>
<li>Dużo drobnych poprawek UI i działania aplikacji.</li>
</ul>
<!--<i>

View File

@ -22,6 +22,7 @@ import android.util.Pair;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.multidex.MultiDex;
import androidx.work.Configuration;
import com.chuckerteam.chucker.api.ChuckerCollector;
@ -59,6 +60,8 @@ import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import cat.ereza.customactivityoncrash.config.CaocConfig;
import dagger.android.AndroidInjector;
import dagger.android.support.DaggerApplication;
import im.wangchao.mhttp.MHttp;
import im.wangchao.mhttp.internal.cookie.PersistentCookieJar;
import im.wangchao.mhttp.internal.cookie.cache.SetCookieCache;
@ -77,6 +80,7 @@ import pl.szczodrzynski.edziennik.data.db.modules.debuglog.DebugLog;
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore;
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile;
import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull;
import pl.szczodrzynski.edziennik.di.DaggerAppComponent;
import pl.szczodrzynski.edziennik.network.NetworkUtils;
import pl.szczodrzynski.edziennik.network.TLSSocketFactory;
import pl.szczodrzynski.edziennik.sync.SyncWorker;
@ -90,7 +94,7 @@ import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_
import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_MOBIDZIENNIK;
import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_VULCAN;
public class App extends androidx.multidex.MultiDexApplication implements Configuration.Provider {
public class App extends DaggerApplication implements Configuration.Provider {
private static final String TAG = "App";
public static int profileId = -1;
private Context mContext;
@ -181,6 +185,17 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
return Icon.createWithBitmap(bitmap);
}
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
return DaggerAppComponent.factory().create(this);
}
@Override
public void onCreate() {
super.onCreate();
@ -543,6 +558,7 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
appConfig = new AppConfig(this);
}
}
public void saveConfig()
{
try {
@ -724,5 +740,4 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
devMode = false;
}
}
}

View File

@ -2,19 +2,13 @@ package pl.szczodrzynski.edziennik
import android.app.Activity
import android.app.ActivityManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.content.*
import android.graphics.BitmapFactory
import android.graphics.drawable.BitmapDrawable
import android.os.*
import android.provider.Settings
import android.view.Gravity
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.PopupMenu
import androidx.core.graphics.ColorUtils
import androidx.lifecycle.Observer
@ -31,6 +25,7 @@ import com.mikepenz.materialdrawer.model.ProfileDrawerItem
import com.mikepenz.materialdrawer.model.ProfileSettingDrawerItem
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem
import com.mikepenz.materialdrawer.model.interfaces.IProfile
import dagger.android.support.DaggerAppCompatActivity
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
@ -69,7 +64,6 @@ import pl.szczodrzynski.edziennik.utils.Themes
import pl.szczodrzynski.edziennik.utils.Utils
import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.Utils.dpToPx
import pl.szczodrzynski.edziennik.utils.appManagerIntentList
import pl.szczodrzynski.edziennik.utils.models.NavTarget
import pl.szczodrzynski.navlib.*
import pl.szczodrzynski.navlib.SystemBarsUtil.Companion.COLOR_HALF_TRANSPARENT
@ -84,7 +78,7 @@ import java.io.IOException
import java.util.*
import kotlin.math.roundToInt
class MainActivity : AppCompatActivity() {
class MainActivity : DaggerAppCompatActivity() {
companion object {
var useOldMessages = false
@ -346,7 +340,7 @@ class MainActivity : AppCompatActivity() {
if (!profileListEmpty) {
handleIntent(intent?.extras)
}
app.db.profileDao().getAllFull().observe(this, Observer { profiles ->
app.db.profileDao().allFull.observe(this, Observer { profiles ->
// TODO fix weird -1 profiles ???
profiles.removeAll { it.id < 0 }
drawer.setProfileList(profiles)
@ -363,7 +357,7 @@ class MainActivity : AppCompatActivity() {
if (app.profile != null)
setDrawerItems()
app.db.metadataDao().getUnreadCounts().observe(this, Observer { unreadCounters ->
app.db.metadataDao().unreadCounts.observe(this, Observer { unreadCounters ->
unreadCounters.map {
it.type = it.thingType
}
@ -588,17 +582,28 @@ class MainActivity : AppCompatActivity() {
.setMessage(R.string.app_manager_dialog_text)
.setPositiveButton(R.string.ok) { dialog, which ->
try {
for (intent in appManagerIntentList) {
if (packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
startActivity(intent)
}
}
val intent = Intent()
intent.component = ComponentName(
"com.huawei.systemmanager",
"com.huawei.systemmanager.appcontrol.activity.StartupAppControlActivity"
)
startActivity(intent)
} catch (e: Exception) {
e.printStackTrace()
try {
startActivity(Intent(Settings.ACTION_SETTINGS))
val intent = Intent()
intent.component = ComponentName(
"com.asus.mobilemanager",
"com.asus.mobilemanager.MainActivity"
)
startActivity(intent)
} catch (e: Exception) {
e.printStackTrace()
Toast.makeText(this, R.string.app_manager_open_failed, Toast.LENGTH_SHORT).show()
try {
startActivity(Intent(android.provider.Settings.ACTION_SETTINGS))
} catch (e: Exception) {
e.printStackTrace()
Toast.makeText(this, R.string.app_manager_open_failed, Toast.LENGTH_SHORT).show()
}
}
}
}

View File

@ -90,7 +90,6 @@ class ApiService : Service() {
errorList.add(apiError)
apiError.throwable?.printStackTrace()
if (apiError.isCritical) {
taskRunning?.cancel()
notification.setCriticalError().post()
taskRunning = null
taskIsRunning = false
@ -155,14 +154,10 @@ class ApiService : Service() {
// post an event
EventBus.getDefault().post(ApiTaskStartedEvent(taskProfileId, task.profile))
try {
when (task) {
is EdziennikTask -> task.run(app, taskCallback)
is NotifyTask -> task.run(app, taskCallback)
is ErrorReportTask -> task.run(app, taskCallback, notification, errorList)
}
} catch (e: Exception) {
taskCallback.onError(ApiError(TAG, EXCEPTION_API_TASK).withThrowable(e))
when (task) {
is EdziennikTask -> task.run(app, taskCallback)
is NotifyTask -> task.run(app, taskCallback)
is ErrorReportTask -> task.run(app, taskCallback, notification, errorList)
}
}

View File

@ -150,7 +150,6 @@ const val ERROR_IDZIENNIK_API_OTHER = 451
const val ERROR_TEMPLATE_WEB_OTHER = 801
const val EXCEPTION_API_TASK = 900
const val EXCEPTION_LOGIN_LIBRUS_API_TOKEN = 901
const val EXCEPTION_LOGIN_LIBRUS_PORTAL_TOKEN = 902
const val EXCEPTION_LIBRUS_PORTAL_SYNERGIA_TOKEN = 903

View File

@ -41,43 +41,43 @@ class IdziennikData(val data: DataIdziennik, val onSuccess: () -> Unit) {
when (endpointId) {
ENDPOINT_IDZIENNIK_WEB_TIMETABLE -> {
data.startProgress(R.string.edziennik_progress_endpoint_timetable)
IdziennikWebTimetable(data, onSuccess)
IdziennikWebTimetable(data) { onSuccess() }
}
ENDPOINT_IDZIENNIK_WEB_GRADES -> {
data.startProgress(R.string.edziennik_progress_endpoint_grades)
IdziennikWebGrades(data, onSuccess)
IdziennikWebGrades(data) { onSuccess() }
}
ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES -> {
data.startProgress(R.string.edziennik_progress_endpoint_proposed_grades)
IdziennikWebProposedGrades(data, onSuccess)
IdziennikWebProposedGrades(data) { onSuccess() }
}
ENDPOINT_IDZIENNIK_WEB_EXAMS -> {
data.startProgress(R.string.edziennik_progress_endpoint_exams)
IdziennikWebExams(data, onSuccess)
IdziennikWebExams(data) { onSuccess() }
}
ENDPOINT_IDZIENNIK_WEB_NOTICES -> {
data.startProgress(R.string.edziennik_progress_endpoint_notices)
IdziennikWebNotices(data, onSuccess)
IdziennikWebNotices(data) { onSuccess() }
}
ENDPOINT_IDZIENNIK_WEB_ANNOUNCEMENTS -> {
data.startProgress(R.string.edziennik_progress_endpoint_announcements)
IdziennikWebAnnouncements(data, onSuccess)
IdziennikWebAnnouncements(data) { onSuccess() }
}
ENDPOINT_IDZIENNIK_WEB_ATTENDANCE -> {
data.startProgress(R.string.edziennik_progress_endpoint_attendance)
IdziennikWebAttendance(data, onSuccess)
IdziennikWebAttendance(data) { onSuccess() }
}
ENDPOINT_IDZIENNIK_API_CURRENT_REGISTER -> {
data.startProgress(R.string.edziennik_progress_endpoint_lucky_number)
IdziennikApiCurrentRegister(data, onSuccess)
IdziennikApiCurrentRegister(data) { onSuccess() }
}
ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX -> {
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
IdziennikApiMessagesInbox(data, onSuccess)
IdziennikApiMessagesInbox(data) { onSuccess() }
}
ENDPOINT_IDZIENNIK_API_MESSAGES_SENT -> {
data.startProgress(R.string.edziennik_progress_endpoint_messages_outbox)
IdziennikApiMessagesSent(data, onSuccess)
IdziennikApiMessagesSent(data) { onSuccess() }
}
else -> onSuccess()
}

View File

@ -5,7 +5,7 @@
package pl.szczodrzynski.edziennik.api.v2.librus
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.api.v2.*
import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikInterface
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusData
@ -14,7 +14,9 @@ import pl.szczodrzynski.edziennik.api.v2.librus.firstlogin.LibrusFirstLogin
import pl.szczodrzynski.edziennik.api.v2.librus.login.LibrusLogin
import pl.szczodrzynski.edziennik.api.v2.librus.login.LibrusLoginApi
import pl.szczodrzynski.edziennik.api.v2.librus.login.LibrusLoginSynergia
import pl.szczodrzynski.edziennik.api.v2.librusLoginMethods
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
import pl.szczodrzynski.edziennik.api.v2.prepare
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
import pl.szczodrzynski.edziennik.utils.Utils.d
@ -51,28 +53,12 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|__*/
override fun sync(featureIds: List<Int>, viewId: Int?) {
data.prepare(librusLoginMethods, LibrusFeatures, featureIds, viewId)
login()
}
private fun login() {
d(TAG, "Trying to login with ${data.targetLoginMethodIds}")
if (internalErrorList.isNotEmpty()) {
d(TAG, " - Internal errors:")
internalErrorList.forEach { d(TAG, " - code $it") }
}
LibrusLogin(data) {
data()
}
}
private fun data() {
d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
if (internalErrorList.isNotEmpty()) {
d(TAG, " - Internal errors:")
internalErrorList.forEach { d(TAG, " - code $it") }
}
LibrusData(data) {
completed()
LibrusLogin(data) {
LibrusData(data) {
completed()
}
}
}
@ -116,67 +102,15 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
}
override fun onError(apiError: ApiError) {
if (apiError.errorCode in internalErrorList) {
// finish immediately if the same error occurs twice during the same sync
callback.onError(apiError)
return
}
internalErrorList.add(apiError.errorCode)
when (apiError.errorCode) {
ERROR_LIBRUS_PORTAL_ACCESS_DENIED -> {
data.loginMethods.remove(LOGIN_METHOD_LIBRUS_PORTAL)
data.targetLoginMethodIds.add(LOGIN_METHOD_LIBRUS_PORTAL)
data.targetLoginMethodIds.sort()
data.portalTokenExpiryTime = 0
login()
in internalErrorList -> {
// finish immediately if the same error occurs twice during the same sync
callback.onError(apiError)
}
ERROR_LIBRUS_API_ACCESS_DENIED,
ERROR_LIBRUS_API_TOKEN_EXPIRED -> {
data.loginMethods.remove(LOGIN_METHOD_LIBRUS_API)
data.targetLoginMethodIds.add(LOGIN_METHOD_LIBRUS_API)
data.targetLoginMethodIds.sort()
data.apiTokenExpiryTime = 0
login()
}
ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED -> {
data.loginMethods.remove(LOGIN_METHOD_LIBRUS_SYNERGIA)
data.targetLoginMethodIds.add(LOGIN_METHOD_LIBRUS_SYNERGIA)
data.targetLoginMethodIds.sort()
data.synergiaSessionIdExpiryTime = 0
login()
}
ERROR_LIBRUS_MESSAGES_ACCESS_DENIED -> {
data.loginMethods.remove(LOGIN_METHOD_LIBRUS_MESSAGES)
data.targetLoginMethodIds.add(LOGIN_METHOD_LIBRUS_MESSAGES)
data.targetLoginMethodIds.sort()
data.messagesSessionIdExpiryTime = 0
login()
}
ERROR_LOGIN_LIBRUS_PORTAL_NO_CODE,
ERROR_LOGIN_LIBRUS_PORTAL_CSRF_MISSING,
ERROR_LOGIN_LIBRUS_PORTAL_CODE_REVOKED,
ERROR_LOGIN_LIBRUS_PORTAL_CODE_EXPIRED -> {
login()
}
ERROR_LOGIN_LIBRUS_PORTAL_NO_REFRESH,
ERROR_LOGIN_LIBRUS_PORTAL_REFRESH_REVOKED,
ERROR_LOGIN_LIBRUS_PORTAL_REFRESH_INVALID -> {
data.portalRefreshToken = null
login()
}
ERROR_LOGIN_LIBRUS_SYNERGIA_TOKEN_INVALID,
ERROR_LOGIN_LIBRUS_SYNERGIA_NO_TOKEN,
ERROR_LOGIN_LIBRUS_SYNERGIA_NO_SESSION_ID -> {
login()
}
ERROR_LOGIN_LIBRUS_MESSAGES_NO_SESSION_ID -> {
login()
}
// TODO PORTAL CAPTCHA
ERROR_LIBRUS_API_TIMETABLE_NOT_PUBLIC,
ERROR_LIBRUS_API_LUCKY_NUMBER_NOT_ACTIVE,
ERROR_LIBRUS_API_NOTES_NOT_ACTIVE -> {
data()
CODE_INTERNAL_LIBRUS_ACCOUNT_410 -> {
internalErrorList.add(apiError.errorCode)
loginStore.removeLoginData("refreshToken") // force a clean login
//loginLibrus()
}
else -> callback.onError(apiError)
}

View File

@ -45,96 +45,92 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
*/
ENDPOINT_LIBRUS_API_ME -> {
data.startProgress(R.string.edziennik_progress_endpoint_student_info)
LibrusApiMe(data, onSuccess)
LibrusApiMe(data) { onSuccess() }
}
ENDPOINT_LIBRUS_API_SCHOOLS -> {
data.startProgress(R.string.edziennik_progress_endpoint_school_info)
LibrusApiSchools(data, onSuccess)
LibrusApiSchools(data) { onSuccess() }
}
ENDPOINT_LIBRUS_API_CLASSES -> {
data.startProgress(R.string.edziennik_progress_endpoint_classes)
LibrusApiClasses(data, onSuccess)
LibrusApiClasses(data) { onSuccess() }
}
ENDPOINT_LIBRUS_API_VIRTUAL_CLASSES -> {
data.startProgress(R.string.edziennik_progress_endpoint_teams)
LibrusApiVirtualClasses(data, onSuccess)
LibrusApiVirtualClasses(data) { onSuccess() }
}
ENDPOINT_LIBRUS_API_UNITS -> {
data.startProgress(R.string.edziennik_progress_endpoint_units)
LibrusApiUnits(data, onSuccess)
LibrusApiUnits(data) { onSuccess() }
}
ENDPOINT_LIBRUS_API_USERS -> {
data.startProgress(R.string.edziennik_progress_endpoint_teachers)
LibrusApiUsers(data, onSuccess)
LibrusApiUsers(data) { onSuccess() }
}
ENDPOINT_LIBRUS_API_SUBJECTS -> {
data.startProgress(R.string.edziennik_progress_endpoint_subjects)
LibrusApiSubjects(data, onSuccess)
LibrusApiSubjects(data) { onSuccess() }
}
ENDPOINT_LIBRUS_API_CLASSROOMS -> {
data.startProgress(R.string.edziennik_progress_endpoint_classrooms)
LibrusApiClassrooms(data, onSuccess)
LibrusApiClassrooms(data) { onSuccess() }
}
// TODO push config
// TODO timetable
ENDPOINT_LIBRUS_API_NORMAL_GRADES -> {
data.startProgress(R.string.edziennik_progress_endpoint_grades)
LibrusApiGrades(data, onSuccess)
}
ENDPOINT_LIBRUS_API_NORMAL_GC -> {
data.startProgress(R.string.edziennik_progress_endpoint_grade_categories)
LibrusApiGradeCategories(data, onSuccess)
LibrusApiGrades(data) { onSuccess() }
}
// TODO grades
ENDPOINT_LIBRUS_API_EVENT_TYPES -> {
data.startProgress(R.string.edziennik_progress_endpoint_event_types)
LibrusApiEventTypes(data, onSuccess)
LibrusApiEventTypes(data) { onSuccess() }
}
ENDPOINT_LIBRUS_API_EVENTS -> {
data.startProgress(R.string.edziennik_progress_endpoint_events)
LibrusApiEvents(data, onSuccess)
LibrusApiEvents(data) { onSuccess() }
}
ENDPOINT_LIBRUS_API_HOMEWORK -> {
data.startProgress(R.string.edziennik_progress_endpoint_homework)
LibrusApiHomework(data, onSuccess)
LibrusApiHomework(data) { onSuccess() }
}
ENDPOINT_LIBRUS_API_LUCKY_NUMBER -> {
data.startProgress(R.string.edziennik_progress_endpoint_lucky_number)
LibrusApiLuckyNumber(data, onSuccess)
LibrusApiLuckyNumber(data) { onSuccess() }
}
ENDPOINT_LIBRUS_API_NOTICE_TYPES -> {
data.startProgress(R.string.edziennik_progress_endpoint_notice_types)
LibrusApiNoticeTypes(data, onSuccess)
LibrusApiNoticeTypes(data) { onSuccess() }
}
ENDPOINT_LIBRUS_API_NOTICES -> {
data.startProgress(R.string.edziennik_progress_endpoint_notices)
LibrusApiNotices(data, onSuccess)
LibrusApiNotices(data) { onSuccess() }
}
ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES -> {
data.startProgress(R.string.edziennik_progress_endpoint_attendance_types)
LibrusApiAttendanceTypes(data, onSuccess)
LibrusApiAttendanceTypes(data) { onSuccess() }
}
ENDPOINT_LIBRUS_API_ATTENDANCES -> {
data.startProgress(R.string.edziennik_progress_endpoint_attendance)
LibrusApiAttendances(data, onSuccess)
LibrusApiAttendances(data) { onSuccess() }
}
ENDPOINT_LIBRUS_API_ANNOUNCEMENTS -> {
data.startProgress(R.string.edziennik_progress_endpoint_announcements)
LibrusApiAnnouncements(data, onSuccess)
LibrusApiAnnouncements(data) { onSuccess() }
}
ENDPOINT_LIBRUS_API_PT_MEETINGS -> {
data.startProgress(R.string.edziennik_progress_endpoint_pt_meetings)
LibrusApiPtMeetings(data, onSuccess)
LibrusApiPtMeetings(data) { onSuccess() }
}
ENDPOINT_LIBRUS_API_TEACHER_FREE_DAY_TYPES -> {
data.startProgress(R.string.edziennik_progress_endpoint_teacher_free_day_types)
LibrusApiTeacherFreeDayTypes(data, onSuccess)
LibrusApiTeacherFreeDayTypes(data) { onSuccess() }
}
ENDPOINT_LIBRUS_API_TEACHER_FREE_DAYS -> {
data.startProgress(R.string.edziennik_progress_endpoint_teacher_free_days)
LibrusApiTeacherFreeDays(data, onSuccess)
LibrusApiTeacherFreeDays(data) { onSuccess() }
}
/**
@ -142,11 +138,11 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
*/
ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK -> {
data.startProgress(R.string.edziennik_progress_endpoint_homework)
LibrusSynergiaHomework(data, onSuccess)
LibrusSynergiaHomework(data) { onSuccess() }
}
ENDPOINT_LIBRUS_SYNERGIA_INFO -> {
data.startProgress(R.string.edziennik_progress_endpoint_student_info)
LibrusSynergiaInfo(data, onSuccess)
LibrusSynergiaInfo(data) { onSuccess() }
}
/**
@ -154,11 +150,11 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
*/
ENDPOINT_LIBRUS_MESSAGES_RECEIVED -> {
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
LibrusMessagesGetList(data, type = Message.TYPE_RECEIVED, onSuccess = onSuccess)
LibrusMessagesGetList(data, type = Message.TYPE_RECEIVED) { onSuccess() }
}
ENDPOINT_LIBRUS_MESSAGES_SENT -> {
data.startProgress(R.string.edziennik_progress_endpoint_messages_outbox)
LibrusMessagesGetList(data, type = Message.TYPE_SENT, onSuccess = onSuccess)
LibrusMessagesGetList(data, type = Message.TYPE_SENT) { onSuccess() }
}
else -> onSuccess()

View File

@ -12,17 +12,13 @@ import okhttp3.Cookie
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.parser.Parser
import org.redundent.kotlin.xml.PrintOptions
import org.redundent.kotlin.xml.xml
import pl.szczodrzynski.edziennik.api.v2.*
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
import pl.szczodrzynski.edziennik.get
import pl.szczodrzynski.edziennik.utils.Utils.d
import java.io.StringWriter
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.transform.OutputKeys
import javax.xml.transform.TransformerFactory
import javax.xml.transform.dom.DOMSource
import javax.xml.transform.stream.StreamResult
open class LibrusMessages(open val data: DataLibrus) {
companion object {
@ -84,27 +80,7 @@ open class LibrusMessages(open val data: DataLibrus) {
.secure().httpOnly().build()
))
val docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
val doc = docBuilder.newDocument()
val serviceElement = doc.createElement("service")
val headerElement = doc.createElement("header")
val dataElement = doc.createElement("data")
for ((key, value) in parameters.orEmpty()) {
val element = doc.createElement(key)
element.appendChild(doc.createTextNode(value.toString()))
dataElement.appendChild(element)
}
serviceElement.appendChild(headerElement)
serviceElement.appendChild(dataElement)
doc.appendChild(serviceElement)
val transformer = TransformerFactory.newInstance().newTransformer()
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes")
val stringWriter = StringWriter()
transformer.transform(DOMSource(doc), StreamResult(stringWriter))
val requestXml = stringWriter.toString()
/*val requestXml = xml("service") {
val requestXml = xml("service") {
"header" { }
"data" {
for ((key, value) in parameters.orEmpty()) {
@ -116,7 +92,7 @@ open class LibrusMessages(open val data: DataLibrus) {
}.toString(PrintOptions(
singleLineTextElements = true,
useSelfClosingTags = true
))*/
))
Request.builder()
.url("$LIBRUS_MESSAGES_URL/$endpoint")

View File

@ -44,10 +44,7 @@ open class LibrusPortal(open val data: DataLibrus) {
"Access token is invalid" -> ERROR_LIBRUS_PORTAL_ACCESS_DENIED
"ApiDisabled" -> ERROR_LIBRUS_PORTAL_API_DISABLED
"Account not found" -> ERROR_LIBRUS_PORTAL_SYNERGIA_NOT_FOUND
else -> when (json.getString("hint")) {
"Error while decoding to JSON" -> ERROR_LIBRUS_PORTAL_ACCESS_DENIED
else -> ERROR_LIBRUS_PORTAL_OTHER
}
else -> ERROR_LIBRUS_PORTAL_OTHER
}.let { errorCode ->
data.error(ApiError(tag, errorCode)
.withApiResponse(json)

View File

@ -1,48 +0,0 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2019-11-5
*/
package pl.szczodrzynski.edziennik.api.v2.librus.data.api
import android.graphics.Color
import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
import pl.szczodrzynski.edziennik.api.v2.librus.ENDPOINT_LIBRUS_API_NORMAL_GC
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusApi
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeCategory
class LibrusApiGradeCategories(override val data: DataLibrus,
val onSuccess: () -> Unit) : LibrusApi(data) {
companion object {
const val TAG = "LibrusApiGradeCategories"
}
init {
apiGet(TAG, "Grades/Categories") { json ->
json.getJsonArray("Categories")?.asJsonObjectList()?.forEach { category ->
val id = category.getLong("Id") ?: return@forEach
val name = category.getString("Name") ?: ""
val weight = when (category.getBoolean("CountToTheAverage")) {
true -> category.getFloat("Weight") ?: 0f
else -> 0f
}
val color = category.getJsonObject("Color")?.getInt("Id")
?.let { data.getColor(it) } ?: Color.BLUE
val gradeCategoryObject = GradeCategory(
profileId,
id,
weight,
color,
name
)
data.gradeCategories.put(id, gradeCategoryObject)
}
data.setSyncNext(ENDPOINT_LIBRUS_API_NORMAL_GC, SYNC_ALWAYS)
onSuccess()
}
}
}

View File

@ -42,7 +42,7 @@ class MobidziennikData(val data: DataMobidziennik, val onSuccess: () -> Unit) {
when (endpointId) {
ENDPOINT_MOBIDZIENNIK_API_MAIN -> {
data.startProgress(R.string.edziennik_progress_endpoint_data)
MobidziennikApi(data, onSuccess)
MobidziennikApi(data) { onSuccess() }
}
ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX -> {
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
@ -75,4 +75,4 @@ class MobidziennikData(val data: DataMobidziennik, val onSuccess: () -> Unit) {
else -> onSuccess()
}
}
}
}

View File

@ -390,6 +390,8 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
}
fun error(apiError: ApiError) {
if (apiError.isCritical)
cancel()
callback.onError(apiError)
}

View File

@ -38,39 +38,35 @@ class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) {
when (endpointId) {
ENDPOINT_VULCAN_API_DICTIONARIES -> {
data.startProgress(R.string.edziennik_progress_endpoint_dictionaries)
VulcanApiDictionaries(data, onSuccess)
VulcanApiDictionaries(data) { onSuccess() }
}
ENDPOINT_VULCAN_API_GRADES -> {
data.startProgress(R.string.edziennik_progress_endpoint_grades)
VulcanApiGrades(data, onSuccess)
VulcanApiGrades(data) { onSuccess() }
}
ENDPOINT_VULCAN_API_GRADES_SUMMARY -> {
data.startProgress(R.string.edziennik_progress_endpoint_proposed_grades)
VulcanApiProposedGrades(data, onSuccess)
VulcanApiProposedGrades(data) { onSuccess() }
}
ENDPOINT_VULCAN_API_EVENTS -> {
data.startProgress(R.string.edziennik_progress_endpoint_events)
VulcanApiEvents(data, isHomework = false, onSuccess = onSuccess)
VulcanApiEvents(data, isHomework = false) { onSuccess() }
}
ENDPOINT_VULCAN_API_HOMEWORK -> {
data.startProgress(R.string.edziennik_progress_endpoint_homework)
VulcanApiEvents(data, isHomework = true, onSuccess = onSuccess)
VulcanApiEvents(data, isHomework = true) { onSuccess() }
}
ENDPOINT_VULCAN_API_NOTICES -> {
data.startProgress(R.string.edziennik_progress_endpoint_notices)
VulcanApiNotices(data, onSuccess)
VulcanApiNotices(data) { onSuccess() }
}
ENDPOINT_VULCAN_API_ATTENDANCE -> {
data.startProgress(R.string.edziennik_progress_endpoint_attendance)
VulcanApiAttendance(data, onSuccess)
VulcanApiAttendance(data) { onSuccess() }
}
ENDPOINT_VULCAN_API_MESSAGES_INBOX -> {
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
VulcanApiMessagesInbox(data, onSuccess)
}
ENDPOINT_VULCAN_API_MESSAGES_SENT -> {
data.startProgress(R.string.edziennik_progress_endpoint_messages_outbox)
VulcanApiMessagesSent(data, onSuccess)
VulcanApiMessagesInbox(data) { onSuccess() }
}
else -> onSuccess()
}

View File

@ -11,7 +11,6 @@ import pl.szczodrzynski.edziennik.api.v2.vulcan.ENDPOINT_VULCAN_API_MESSAGES_INB
import pl.szczodrzynski.edziennik.api.v2.vulcan.data.VulcanApi
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipient
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
import pl.szczodrzynski.edziennik.utils.models.Date
@ -21,68 +20,64 @@ class VulcanApiMessagesInbox(override val data: DataVulcan, val onSuccess: () ->
const val TAG = "VulcanApiMessagesInbox"
}
init {
data.profile?.also { profile ->
init { data.profile?.also { profile ->
val startDate: String = when (profile.empty) {
true -> profile.getSemesterStart(profile.currentSemester).stringY_m_d
else -> Date.getToday().stepForward(0, -1, 0).stringY_m_d
val startDate: String = when (profile.empty) {
true -> profile.getSemesterStart(profile.currentSemester).stringY_m_d
else -> Date.getToday().stepForward(0, -1, 0).stringY_m_d
}
val endDate: String = profile.getSemesterEnd(profile.currentSemester).stringY_m_d
apiGet(TAG, VULCAN_API_ENDPOINT_MESSAGES_RECEIVED, parameters = mapOf(
"DataPoczatkowa" to startDate,
"DataKoncowa" to endDate,
"LoginId" to data.studentLoginId,
"IdUczen" to data.studentId
)) { json, _ ->
json.getJsonArray("Data").asJsonObjectList()?.forEach { message ->
val id = message.getLong("WiadomoscId") ?: return@forEach
val subject = message.getString("Tytul") ?: ""
val body = message.getString("Tresc") ?: ""
val senderLoginId = message.getString("NadawcaId") ?: return@forEach
val senderId = data.teacherList
.singleOrNull { it.loginId == senderLoginId }?.id ?: return@forEach
val addedDate = message.getLong("DataWyslaniaUnixEpoch")?.let { it * 1000 } ?: -1
val readDate = message.getLong("DataPrzeczytaniaUnixEpoch")?.let { it * 1000 } ?: -1
val messageObject = Message(
profileId,
id,
subject,
body,
Message.TYPE_RECEIVED,
senderId,
-1
)
val messageRecipientObject = MessageRecipient(
profileId,
-1,
-1,
readDate,
id
)
data.messageList.add(messageObject)
data.messageRecipientList.add(messageRecipientObject)
data.metadataList.add(Metadata(
profileId,
Metadata.TYPE_MESSAGE,
id,
readDate > 0,
readDate > 0,
addedDate
))
}
val endDate: String = profile.getSemesterEnd(profile.currentSemester).stringY_m_d
apiGet(TAG, VULCAN_API_ENDPOINT_MESSAGES_RECEIVED, parameters = mapOf(
"DataPoczatkowa" to startDate,
"DataKoncowa" to endDate,
"LoginId" to data.studentLoginId,
"IdUczen" to data.studentId
)) { json, _ ->
json.getJsonArray("Data").asJsonObjectList()?.forEach { message ->
val id = message.getLong("WiadomoscId") ?: return@forEach
val subject = message.getString("Tytul") ?: ""
val body = message.getString("Tresc") ?: ""
val senderLoginId = message.getString("NadawcaId") ?: return@forEach
val senderId = data.teacherList
.singleOrNull { it.loginId == senderLoginId }?.id ?: return@forEach
val sentDate = message.getLong("DataWyslaniaUnixEpoch")?.let { it * 1000 }
?: -1
val readDate = message.getLong("DataPrzeczytaniaUnixEpoch")?.let { it * 1000 }
?: -1
val messageObject = Message(
profileId,
id,
subject,
body,
TYPE_RECEIVED,
senderId,
-1
)
val messageRecipientObject = MessageRecipient(
profileId,
-1,
-1,
readDate,
id
)
data.messageList.add(messageObject)
data.messageRecipientList.add(messageRecipientObject)
data.metadataList.add(Metadata(
profileId,
Metadata.TYPE_MESSAGE,
id,
readDate > 0,
readDate > 0,
sentDate
))
}
data.setSyncNext(ENDPOINT_VULCAN_API_MESSAGES_INBOX, SYNC_ALWAYS)
onSuccess()
}
} ?: onSuccess()
}
data.setSyncNext(ENDPOINT_VULCAN_API_MESSAGES_INBOX, SYNC_ALWAYS)
onSuccess()
}
} ?: onSuccess()}
}

View File

@ -1,99 +0,0 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2019-11-5
*/
package pl.szczodrzynski.edziennik.api.v2.vulcan.data.api
import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_MESSAGES
import pl.szczodrzynski.edziennik.api.v2.VULCAN_API_ENDPOINT_MESSAGES_SENT
import pl.szczodrzynski.edziennik.api.v2.vulcan.DataVulcan
import pl.szczodrzynski.edziennik.api.v2.vulcan.ENDPOINT_VULCAN_API_MESSAGES_SENT
import pl.szczodrzynski.edziennik.api.v2.vulcan.data.VulcanApi
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipient
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
import pl.szczodrzynski.edziennik.utils.models.Date
class VulcanApiMessagesSent(override val data: DataVulcan, val onSuccess: () -> Unit) : VulcanApi(data) {
companion object {
const val TAG = "VulcanApiMessagesSent"
}
init {
data.profile?.also { profile ->
val startDate: String = when (profile.empty) {
true -> profile.getSemesterStart(profile.currentSemester).stringY_m_d
else -> Date.getToday().stepForward(0, -1, 0).stringY_m_d
}
val endDate: String = profile.getSemesterEnd(profile.currentSemester).stringY_m_d
apiGet(TAG, VULCAN_API_ENDPOINT_MESSAGES_SENT, parameters = mapOf(
"DataPoczatkowa" to startDate,
"DataKoncowa" to endDate,
"LoginId" to data.studentLoginId,
"IdUczen" to data.studentId
)) { json, _ ->
json.getJsonArray("Data")?.asJsonObjectList()?.forEach { message ->
val id = message.getLong("WiadomoscId") ?: return@forEach
val subject = message.getString("Tytul") ?: ""
val body = message.getString("Tresc") ?: ""
val readBy = message.getInt("Przeczytane") ?: 0
val unreadBy = message.getInt("Nieprzeczytane") ?: 0
val sentDate = message.getLong("DataWyslaniaUnixEpoch")?.let { it * 1000 } ?: -1
val messageObject = Message(
profileId,
id,
subject,
body,
TYPE_SENT,
-1,
-1
)
message.getJsonArray("Adresaci")?.asJsonObjectList()
?.forEachIndexed { _, recipient ->
val recipientLoginId = recipient.getString("LoginId")
?: return@forEachIndexed
val recipientId = data.teacherList.singleOrNull { it.loginId == recipientLoginId }?.id
?: return@forEachIndexed
val readDate: Long = when (readBy) {
0 -> 0
else -> when (unreadBy) {
0 -> 1
else -> -1
}
}
val messageRecipientObject = MessageRecipient(
profileId,
recipientId,
-1,
readDate,
id
)
data.messageRecipientList.add(messageRecipientObject)
}
data.messageList.add(messageObject)
data.metadataList.add(Metadata(
profileId,
Metadata.TYPE_MESSAGE,
id,
true,
true,
sentDate
))
}
data.setSyncNext(ENDPOINT_VULCAN_API_MESSAGES_SENT, 1 * DAY, DRAWER_ITEM_MESSAGES)
onSuccess()
}
}
}
}

View File

@ -6,6 +6,8 @@ package pl.szczodrzynski.edziennik.api.v2.vulcan.data.api
import pl.szczodrzynski.edziennik.api.v2.vulcan.DataVulcan
import pl.szczodrzynski.edziennik.api.v2.vulcan.data.VulcanApi
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.getJsonArray
class VulcanApiTemplate(override val data: DataVulcan, val onSuccess: () -> Unit) : VulcanApi(data) {
companion object {
@ -13,12 +15,10 @@ class VulcanApiTemplate(override val data: DataVulcan, val onSuccess: () -> Unit
}
init {
/* data.profile?.also { profile ->
apiGet(TAG, VULCAN_API_ENDPOINT_) { json, _ ->
/* apiGet(TAG, VULCAN_API_ENDPOINT_) { json, _ ->
data.setSyncNext(ENDPOINT_VULCAN_API_, SYNC_ALWAYS)
onSuccess()
}
data.setSyncNext(ENDPOINT_VULCAN_API_, SYNC_ALWAYS)
onSuccess()
} */
}
}

View File

@ -10,6 +10,8 @@ import androidx.room.TypeConverters;
import androidx.room.migration.Migration;
import androidx.sqlite.db.SupportSQLiteDatabase;
import javax.inject.Singleton;
import pl.szczodrzynski.edziennik.data.db.converters.ConverterDate;
import pl.szczodrzynski.edziennik.data.db.converters.ConverterDateInt;
import pl.szczodrzynski.edziennik.data.db.converters.ConverterJsonObject;
@ -74,6 +76,7 @@ import pl.szczodrzynski.edziennik.data.db.modules.teams.Team;
import pl.szczodrzynski.edziennik.data.db.modules.teams.TeamDao;
import pl.szczodrzynski.edziennik.utils.models.Date;
@Singleton
@Database(entities = {
Grade.class,
//GradeCategory.class,
@ -114,33 +117,60 @@ import pl.szczodrzynski.edziennik.utils.models.Date;
public abstract class AppDb extends RoomDatabase {
public abstract GradeDao gradeDao();
//public abstract GradeCategoryDao gradeCategoryDao();
public abstract TeacherDao teacherDao();
public abstract TeacherAbsenceDao teacherAbsenceDao();
public abstract TeacherAbsenceTypeDao teacherAbsenceTypeDao();
public abstract SubjectDao subjectDao();
public abstract NoticeDao noticeDao();
public abstract LessonDao lessonDao();
public abstract LessonChangeDao lessonChangeDao();
public abstract TeamDao teamDao();
public abstract AttendanceDao attendanceDao();
public abstract EventDao eventDao();
public abstract EventTypeDao eventTypeDao();
public abstract LoginStoreDao loginStoreDao();
public abstract ProfileDao profileDao();
public abstract LuckyNumberDao luckyNumberDao();
public abstract AnnouncementDao announcementDao();
public abstract GradeCategoryDao gradeCategoryDao();
public abstract FeedbackMessageDao feedbackMessageDao();
public abstract MessageDao messageDao();
public abstract MessageRecipientDao messageRecipientDao();
public abstract DebugLogDao debugLogDao();
public abstract EndpointTimerDao endpointTimerDao();
public abstract LessonRangeDao lessonRangeDao();
public abstract NotificationDao notificationDao();
public abstract ClassroomDao classroomDao();
public abstract NoticeTypeDao noticeTypeDao();
public abstract AttendanceTypeDao attendanceTypeDao();
public abstract MetadataDao metadataDao();
private static volatile AppDb INSTANCE;

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2019-11-4
*/
package pl.szczodrzynski.edziennik.data.db
import android.content.Context
import dagger.Module
import dagger.Provides
import javax.inject.Singleton
@Module
internal class DatabaseModule {
@Singleton
@Provides
fun provideDatabase(context: Context) = AppDb.getDatabase(context)
@Singleton
@Provides
fun provideEventDao(database: AppDb) = database.eventDao()
@Singleton
@Provides
fun provideMetadataDao(database: AppDb) = database.metadataDao()
}

View File

@ -1,19 +1,22 @@
package pl.szczodrzynski.edziennik.data.db.modules.events;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData;
import androidx.sqlite.db.SimpleSQLiteQuery;
import androidx.sqlite.db.SupportSQLiteQuery;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.RawQuery;
import androidx.room.Transaction;
import androidx.annotation.NonNull;
import android.util.Log;
import androidx.sqlite.db.SimpleSQLiteQuery;
import androidx.sqlite.db.SupportSQLiteQuery;
import java.util.List;
import javax.inject.Singleton;
import pl.szczodrzynski.edziennik.utils.models.Date;
import pl.szczodrzynski.edziennik.utils.models.Time;
@ -21,6 +24,7 @@ import static pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata.TYPE_
import static pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata.TYPE_HOMEWORK;
import static pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata.TYPE_LESSON_CHANGE;
@Singleton
@Dao
public abstract class EventDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
@ -34,26 +38,32 @@ public abstract class EventDao {
@Query("DELETE FROM events WHERE profileId = :profileId AND eventId = :id")
public abstract void remove(int profileId, long id);
@Query("DELETE FROM metadata WHERE profileId = :profileId AND thingType = :thingType AND thingId = :thingId")
public abstract void removeMetadata(int profileId, int thingType, long thingId);
@Transaction
public void remove(int profileId, int type, long id) {
remove(profileId, id);
removeMetadata(profileId, type == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, id);
}
@Transaction
public void remove(Event event) {
remove(event.profileId, event.type, event.id);
}
@Transaction
public void remove(int profileId, Event event) {
remove(profileId, event.type, event.id);
}
@Query("DELETE FROM events WHERE teamId = :teamId AND eventId = :id")
public abstract void removeByTeamId(long teamId, long id);
@RawQuery(observedEntities = {Event.class})
abstract LiveData<List<EventFull>> getAll(SupportSQLiteQuery query);
public LiveData<List<EventFull>> getAll(int profileId, String filter) {
String query = "SELECT \n" +
"*, \n" +
@ -71,24 +81,31 @@ public abstract class EventDao {
Log.d("DB", query);
return getAll(new SimpleSQLiteQuery(query));
}
public LiveData<List<EventFull>> getAll(int profileId) {
return getAll(profileId, "1");
}
public List<EventFull> getAllNow(int profileId) {
return getAllNow(profileId, "1");
}
public LiveData<List<EventFull>> getAllWhere(int profileId, String filter) {
return getAll(profileId, filter);
}
public LiveData<List<EventFull>> getAllByType(int profileId, int type, String filter) {
return getAll(profileId, "eventType = "+type+" AND "+filter);
}
public LiveData<List<EventFull>> getAllByDate(int profileId, @NonNull Date date) {
return getAll(profileId, "eventDate = '"+date.getStringY_m_d()+"'");
}
public List<EventFull> getAllByDateNow(int profileId, @NonNull Date date) {
return getAllNow(profileId, "eventDate = '"+date.getStringY_m_d()+"'");
}
public LiveData<List<EventFull>> getAllByDateTime(int profileId, @NonNull Date date, Time time) {
if (time == null)
return getAllByDate(profileId, date);
@ -97,6 +114,7 @@ public abstract class EventDao {
@RawQuery
abstract List<EventFull> getAllNow(SupportSQLiteQuery query);
public List<EventFull> getAllNow(int profileId, String filter) {
return getAllNow(new SimpleSQLiteQuery("SELECT \n" +
"*, \n" +
@ -112,6 +130,7 @@ public abstract class EventDao {
"WHERE events.profileId = "+profileId+" AND events.eventBlacklisted = 0 AND "+filter+"\n" +
"ORDER BY eventStartTime, addedDate ASC"));
}
public List<EventFull> getNotNotifiedNow(int profileId) {
return getAllNow(profileId, "notified = 0");
}

View File

@ -8,7 +8,6 @@ import androidx.room.Entity;
import androidx.room.Ignore;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull;
@ -74,7 +73,7 @@ public class LoginStore {
if (data == null)
return defaultValue;
JsonElement element = data.get(key);
if (element != null && !(element instanceof JsonNull)) {
if (element != null) {
return element.getAsString();
}
return defaultValue;
@ -84,7 +83,7 @@ public class LoginStore {
if (data == null)
return defaultValue;
JsonElement element = data.get(key);
if (element != null && !(element instanceof JsonNull)) {
if (element != null) {
return element.getAsInt();
}
return defaultValue;
@ -94,7 +93,7 @@ public class LoginStore {
if (data == null)
return defaultValue;
JsonElement element = data.get(key);
if (element != null && !(element instanceof JsonNull)) {
if (element != null) {
return element.getAsLong();
}
return defaultValue;
@ -104,7 +103,7 @@ public class LoginStore {
if (data == null)
return defaultValue;
JsonElement element = data.get(key);
if (element != null && !(element instanceof JsonNull)) {
if (element != null) {
return element.getAsFloat();
}
return defaultValue;
@ -113,7 +112,7 @@ public class LoginStore {
if (data == null)
return defaultValue;
JsonElement element = data.get(key);
if (element != null && !(element instanceof JsonNull)) {
if (element != null) {
return element.getAsBoolean();
}
return defaultValue;

View File

@ -9,7 +9,8 @@ import androidx.room.Transaction;
import java.util.List;
import pl.szczodrzynski.edziennik.data.db.modules.notices.Notice;
import javax.inject.Singleton;
import pl.szczodrzynski.edziennik.data.db.modules.announcements.Announcement;
import pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance;
import pl.szczodrzynski.edziennik.data.db.modules.events.Event;
@ -17,6 +18,7 @@ import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade;
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange;
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonFull;
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message;
import pl.szczodrzynski.edziennik.data.db.modules.notices.Notice;
import pl.szczodrzynski.edziennik.utils.models.UnreadCounter;
import static pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata.TYPE_ANNOUNCEMENT;
@ -28,6 +30,7 @@ import static pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata.TYPE_
import static pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata.TYPE_MESSAGE;
import static pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata.TYPE_NOTICE;
@Singleton
@Dao
public abstract class MetadataDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
@ -43,7 +46,6 @@ public abstract class MetadataDao {
abstract void updateNotified(int profileId, int thingType, long thingId, boolean notified);
@Transaction
public void setSeen(List<Metadata> metadataList) {
for (Metadata metadata: metadataList) {
@ -152,7 +154,6 @@ public abstract class MetadataDao {
}
@Query("UPDATE metadata SET seen = :seen WHERE profileId = :profileId AND thingType = :thingType")
public abstract void setAllSeen(int profileId, int thingType, boolean seen);
@ -166,7 +167,6 @@ public abstract class MetadataDao {
public abstract void setAllNotified(int profileId, boolean notified);
@Query("SELECT count() FROM metadata WHERE profileId = :profileId AND thingType = :thingType AND seen = 0")
public abstract LiveData<Integer> countUnseen(int profileId, int thingType);
@ -183,7 +183,6 @@ public abstract class MetadataDao {
public abstract LiveData<Integer> countUnseen();
@Query("DELETE FROM metadata WHERE profileId = :profileId AND thingType = :thingType AND thingId = :thingId")
public abstract void delete(int profileId, int thingType, long thingId);
@ -191,12 +190,10 @@ public abstract class MetadataDao {
public abstract void deleteAll(int profileId);
@Query("SELECT profileId, thingType, COUNT(thingId) AS count FROM metadata WHERE seen = 0 GROUP BY profileId, thingType")
public abstract LiveData<List<UnreadCounter>> getUnreadCounts();
@Query("DELETE FROM metadata WHERE profileId = :profileId AND thingType = "+TYPE_GRADE+" AND thingId NOT IN (SELECT gradeId FROM grades WHERE profileId = :profileId);")
public abstract void deleteUnusedGrades(int profileId);

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2019-11-4
*/
package pl.szczodrzynski.edziennik.di
import dagger.Component
import dagger.android.AndroidInjector
import dagger.android.support.AndroidSupportInjectionModule
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.db.DatabaseModule
import javax.inject.Singleton
@Singleton
@Component(modules = [
AndroidSupportInjectionModule::class,
BindingModule::class,
AppModule::class,
DatabaseModule::class
])
interface AppComponent : AndroidInjector<App> {
@Component.Factory
interface Factory : AndroidInjector.Factory<App>
}

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2019-11-4
*/
package pl.szczodrzynski.edziennik.di
import android.content.Context
import dagger.Module
import dagger.Provides
import pl.szczodrzynski.edziennik.App
import javax.inject.Singleton
@Module
internal class AppModule {
@Singleton
@Provides
fun provideContext(app: App): Context = app
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2019-11-4
*/
package pl.szczodrzynski.edziennik.di
import dagger.Module
import dagger.android.ContributesAndroidInjector
import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.di.scopes.PerActivity
import pl.szczodrzynski.edziennik.di.scopes.PerFragment
import pl.szczodrzynski.edziennik.ui.modules.homework.HomeworkFragment
import pl.szczodrzynski.edziennik.ui.modules.homework.list.HomeworkListFragment
@Module
@Suppress("unused")
internal abstract class BindingModule {
/**
* ACTIVITIES
*/
@PerActivity
@ContributesAndroidInjector
abstract fun bindMainActivity(): MainActivity
/**
* FRAGMENTS
*/
@PerFragment
@ContributesAndroidInjector
abstract fun bindHomeworkFragment(): HomeworkFragment
@PerFragment
@ContributesAndroidInjector
abstract fun bindHomeworkListFragment(): HomeworkListFragment
}

View File

@ -0,0 +1,11 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2019-11-4
*/
package pl.szczodrzynski.edziennik.di.scopes
import javax.inject.Scope
@Scope
@Retention(AnnotationRetention.RUNTIME)
annotation class PerActivity

View File

@ -0,0 +1,11 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2019-11-4
*/
package pl.szczodrzynski.edziennik.di.scopes
import javax.inject.Scope
@Scope
@Retention(AnnotationRetention.RUNTIME)
annotation class PerFragment

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2019-11-4
*/
package pl.szczodrzynski.edziennik.ui.base
import android.widget.Toast
import dagger.android.support.DaggerFragment
abstract class BaseFragment<T : BasePresenter<out BaseView>> : DaggerFragment(), BaseView {
abstract var presenter: T
override fun showMessage(text: String) {
Toast.makeText(activity, text, Toast.LENGTH_SHORT).show()
}
override fun onDestroy() {
super.onDestroy()
presenter.onDetachView()
}
}

View File

@ -0,0 +1,18 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2019-11-4
*/
package pl.szczodrzynski.edziennik.ui.base
open class BasePresenter<T : BaseView> {
var view: T? = null
open fun onAttachView(view: T) {
this.view = view
}
open fun onDetachView() {
view = null
}
}

View File

@ -0,0 +1,10 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2019-11-4
*/
package pl.szczodrzynski.edziennik.ui.base
interface BaseView {
fun showMessage(text: String)
}

View File

@ -30,7 +30,6 @@ import androidx.fragment.app.Fragment;
import androidx.work.WorkManager;
import com.afollestad.materialdialogs.MaterialDialog;
import com.chuckerteam.chucker.api.Chucker;
import com.mikepenz.iconics.IconicsColor;
import com.mikepenz.iconics.IconicsDrawable;
import com.mikepenz.iconics.IconicsSize;
@ -51,7 +50,6 @@ import pl.szczodrzynski.edziennik.databinding.CardLuckyNumberBinding;
import pl.szczodrzynski.edziennik.databinding.CardUpdateBinding;
import pl.szczodrzynski.edziennik.databinding.FragmentHomeBinding;
import pl.szczodrzynski.edziennik.receivers.BootReceiver;
import pl.szczodrzynski.edziennik.ui.modules.login.LoginLibrusCaptchaActivity;
import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesComposeActivity;
import pl.szczodrzynski.edziennik.utils.Colors;
import pl.szczodrzynski.edziennik.utils.Themes;
@ -106,14 +104,6 @@ public class HomeFragment extends Fragment {
b.pruneWorkButton.setOnClickListener((v -> WorkManager.getInstance(app).pruneWork()));
b.runChucker.setOnClickListener((v -> {
startActivity(Chucker.getLaunchIntent(activity, 1));
}));
b.librusCaptchaButton.setOnClickListener((v -> {
startActivity(new Intent(activity, LoginLibrusCaptchaActivity.class));
}));
//((TextView)v.findViewById(R.id.nextSync)).setText(getString(R.string.next_sync_format,Time.fromMillis(app.appJobs.syncJobTime).getStringHMS()));

View File

@ -1,132 +0,0 @@
package pl.szczodrzynski.edziennik.ui.modules.homework;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.os.AsyncTask;
import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import java.util.List;
import pl.szczodrzynski.edziennik.App;
import pl.szczodrzynski.edziennik.R;
import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull;
import pl.szczodrzynski.edziennik.ui.dialogs.event.EventManualDialog;
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment;
import pl.szczodrzynski.edziennik.utils.models.Date;
import static pl.szczodrzynski.edziennik.utils.Utils.bs;
public class HomeworkAdapter extends RecyclerView.Adapter<HomeworkAdapter.ViewHolder> {
private Context context;
private List<EventFull> homeworkList;
//getting the context and product list with constructor
public HomeworkAdapter(Context mCtx, List<EventFull> homeworkList) {
this.context = mCtx;
this.homeworkList = homeworkList;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//inflating and returning our view holder
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.row_homework_item, parent, false);
return new ViewHolder(view);
}
public static String dayDiffString(Context context, int dayDiff) {
if (dayDiff > 0) {
if (dayDiff == 1) {
return context.getString(R.string.tomorrow);
}
else if (dayDiff == 2) {
return context.getString(R.string.the_day_after);
}
return HomeFragment.plural(context, R.plurals.time_till_days, Math.abs(dayDiff));
}
else if (dayDiff < 0) {
if (dayDiff == -1) {
return context.getString(R.string.yesterday);
}
else if (dayDiff == -2) {
return context.getString(R.string.the_day_before);
}
return context.getString(R.string.ago_format, HomeFragment.plural(context, R.plurals.time_till_days, Math.abs(dayDiff)));
}
return context.getString(R.string.today);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
App app = (App) context.getApplicationContext();
EventFull homework = homeworkList.get(position);
int diffDays = Date.diffDays(homework.eventDate, Date.getToday());
holder.homeworkItemHomeworkDate.setText(app.getString(R.string.date_relative_format, homework.eventDate.getFormattedString(), dayDiffString(context, diffDays)));
holder.homeworkItemTopic.setText(homework.topic);
holder.homeworkItemSubjectTeacher.setText(context.getString(R.string.homework_subject_teacher_format, bs(homework.subjectLongName), bs(homework.teacherFullName)));
holder.homeworkItemTeamDate.setText(context.getString(R.string.homework_team_date_format, bs(homework.teamName), Date.fromMillis(homework.addedDate).getFormattedStringShort()));
if (!homework.seen) {
holder.homeworkItemTopic.setBackground(context.getResources().getDrawable(R.drawable.bg_rounded_8dp));
holder.homeworkItemTopic.getBackground().setColorFilter(new PorterDuffColorFilter(0x692196f3, PorterDuff.Mode.MULTIPLY));
homework.seen = true;
AsyncTask.execute(() -> {
app.db.metadataDao().setSeen(App.profileId, homework, true);
});
}
else {
holder.homeworkItemTopic.setBackground(null);
}
holder.homeworkItemEdit.setVisibility((homework.addedManually ? View.VISIBLE : View.GONE));
holder.homeworkItemEdit.setOnClickListener(v -> {
new EventManualDialog(context).show(app, homework, null, null, EventManualDialog.DIALOG_HOMEWORK);
});
if (homework.sharedBy == null) {
holder.homeworkItemSharedBy.setVisibility(View.GONE);
}
else if (homework.sharedByName != null) {
holder.homeworkItemSharedBy.setText(app.getString(R.string.event_shared_by_format, (homework.sharedBy.equals("self") ? app.getString(R.string.event_shared_by_self) : homework.sharedByName)));
}
}
@Override
public int getItemCount() {
return homeworkList.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
CardView homeworkItemCard;
TextView homeworkItemTopic;
TextView homeworkItemHomeworkDate;
TextView homeworkItemSharedBy;
TextView homeworkItemSubjectTeacher;
TextView homeworkItemTeamDate;
Button homeworkItemEdit;
ViewHolder(View itemView) {
super(itemView);
homeworkItemCard = itemView.findViewById(R.id.homeworkItemCard);
homeworkItemTopic = itemView.findViewById(R.id.homeworkItemTopic);
homeworkItemHomeworkDate = itemView.findViewById(R.id.homeworkItemHomeworkDate);
homeworkItemSharedBy = itemView.findViewById(R.id.homeworkItemSharedBy);
homeworkItemSubjectTeacher = itemView.findViewById(R.id.homeworkItemSubjectTeacher);
homeworkItemTeamDate = itemView.findViewById(R.id.homeworkItemTeamDate);
homeworkItemEdit = itemView.findViewById(R.id.homeworkItemEdit);
}
}
}

View File

@ -1,84 +1,77 @@
package pl.szczodrzynski.edziennik.ui.modules.homework
import android.os.AsyncTask
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.viewpager.widget.ViewPager
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.databinding.FragmentHomeworkBinding
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
import pl.szczodrzynski.edziennik.ui.base.BaseFragment
import pl.szczodrzynski.edziennik.ui.dialogs.event.EventManualDialog
import pl.szczodrzynski.edziennik.ui.modules.homework.list.HomeworkListFragment
import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesFragment
import pl.szczodrzynski.edziennik.utils.Themes
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetSeparatorItem
import javax.inject.Inject
class HomeworkFragment : Fragment() {
class HomeworkFragment : BaseFragment<HomeworkPresenter>(), HomeworkView {
companion object {
var pageSelection = 0
}
private lateinit var app: App
private lateinit var activity: MainActivity
private lateinit var b: FragmentHomeworkBinding
@Inject
override lateinit var presenter: HomeworkPresenter
@Inject
lateinit var app: App
override val markAsReadSuccessString: String
get() = getString(R.string.main_menu_mark_as_read_success)
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
presenter.onAttachView(this)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
activity = (getActivity() as MainActivity?) ?: return null
if (context == null)
return null
app = activity.application as App
activity = (getActivity() as MainActivity)
context!!.theme.applyStyle(Themes.appTheme, true)
if (app.profile == null)
return inflater.inflate(R.layout.fragment_loading, container, false)
// activity, context and profile is valid
b = FragmentHomeworkBinding.inflate(inflater)
b.refreshLayout.setParent(activity.swipeRefreshLayout)
return b.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
override fun initView() {
// TODO check if app, activity, b can be null
if (app.profile == null || !isAdded)
return
b.refreshLayout.setParent(activity.swipeRefreshLayout)
activity.bottomSheet.prependItems(
BottomSheetPrimaryItem(true)
.withTitle(R.string.menu_add_event)
.withDescription(R.string.menu_add_event_desc)
.withIcon(CommunityMaterial.Icon.cmd_calendar_plus)
.withOnClickListener(View.OnClickListener {
activity.bottomSheet.close()
EventManualDialog(activity).show(app, null, null, null, EventManualDialog.DIALOG_HOMEWORK)
}),
BottomSheetSeparatorItem(true),
BottomSheetPrimaryItem(true)
.withTitle(R.string.menu_mark_as_read)
.withIcon(CommunityMaterial.Icon.cmd_eye_check)
.withOnClickListener(View.OnClickListener {
activity.bottomSheet.close()
AsyncTask.execute { app.db.metadataDao().setAllSeen(App.profileId, Metadata.TYPE_HOMEWORK, true) }
Toast.makeText(activity, R.string.main_menu_mark_as_read_success, Toast.LENGTH_SHORT).show()
}))
.withTitle(R.string.menu_add_event)
.withDescription(R.string.menu_add_event_desc)
.withIcon(CommunityMaterial.Icon.cmd_calendar_plus)
.withOnClickListener(View.OnClickListener { presenter.onAddEventClick() }),
BottomSheetSeparatorItem(true),
BottomSheetPrimaryItem(true)
.withTitle(R.string.menu_mark_as_read)
.withIcon(CommunityMaterial.Icon.cmd_eye_check)
.withOnClickListener(View.OnClickListener { presenter.onMarkAsReadClick() }))
b.viewPager.adapter = MessagesFragment.Adapter(childFragmentManager).also { adapter ->
adapter.addFragment(HomeworkListFragment().also { fragment ->
fragment.arguments = Bundle().also { args ->
args.putInt("homeworkDate", HomeworkDate.CURRENT)
}
}, getString(R.string.homework_tab_current))
adapter.addFragment(HomeworkListFragment().also { fragment ->
fragment.arguments = Bundle().also { args ->
args.putInt("homeworkDate", HomeworkDate.PAST)
}
}, getString(R.string.homework_tab_past))
adapter.addFragment(HomeworkListFragment.newInstance(HomeworkDate.CURRENT), getString(R.string.homework_tab_current))
adapter.addFragment(HomeworkListFragment.newInstance(HomeworkDate.PAST), getString(R.string.homework_tab_past))
}
b.viewPager.currentItem = pageSelection
@ -86,9 +79,7 @@ class HomeworkFragment : Fragment() {
b.viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
override fun onPageSelected(position: Int) {
pageSelection = position
}
override fun onPageSelected(position: Int) = presenter.onPageSelected(position)
})
b.tabLayout.setupWithViewPager(b.viewPager)
@ -96,11 +87,21 @@ class HomeworkFragment : Fragment() {
activity.navView.bottomBar.fabEnable = true
activity.navView.bottomBar.fabExtendedText = getString(R.string.add)
activity.navView.bottomBar.fabIcon = CommunityMaterial.Icon2.cmd_plus
activity.navView.setFabOnClickListener(View.OnClickListener {
EventManualDialog(activity).show(app, null, null, null, EventManualDialog.DIALOG_HOMEWORK)
})
activity.navView.setFabOnClickListener(View.OnClickListener { presenter.onHomeworkAddFabClick() })
activity.gainAttention()
activity.gainAttentionFAB()
}
override fun setPageSelection(position: Int) {
pageSelection = position
}
override fun closeBottomSheet() {
activity.bottomSheet.close()
}
override fun showAddHomeworkDialog() {
EventManualDialog(activity).show(app, null, null, null, EventManualDialog.DIALOG_HOMEWORK)
}
}

View File

@ -1,77 +0,0 @@
package pl.szczodrzynski.edziennik.ui.modules.homework
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.databinding.HomeworkListBinding
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
import pl.szczodrzynski.edziennik.getInt
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.Themes
class HomeworkListFragment : Fragment() {
private lateinit var app: App
private lateinit var activity: MainActivity
private lateinit var b: HomeworkListBinding
private var homeworkDate = HomeworkDate.CURRENT
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
activity = (getActivity() as MainActivity?) ?: return null
if (context == null)
return null
app = activity.application as App
context!!.theme.applyStyle(Themes.appTheme, true)
if (app.profile == null)
return inflater.inflate(R.layout.fragment_loading, container, false)
// activity, context and profile is valid
b = HomeworkListBinding.inflate(inflater)
return b.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
// TODO check if app, activity, b can be null
if (app.profile == null || !isAdded)
return
if (arguments != null) {
homeworkDate = arguments.getInt("homeworkDate", HomeworkDate.CURRENT)
}
val layoutManager = LinearLayoutManager(context)
layoutManager.reverseLayout = true
layoutManager.stackFromEnd = true
b.homeworkView.setHasFixedSize(true)
b.homeworkView.layoutManager = layoutManager
val filter = when(homeworkDate) {
HomeworkDate.CURRENT -> "eventDate > '" + Date.getToday().stringY_m_d + "'"
else -> "eventDate <= '" + Date.getToday().stringY_m_d + "'"
}
app.db.eventDao()
.getAllByType(App.profileId, Event.TYPE_HOMEWORK, filter)
.observe(this, Observer { homeworkList ->
if (app.profile == null || !isAdded) return@Observer
if (homeworkList != null && homeworkList.size > 0) {
val adapter = HomeworkAdapter(context, homeworkList)
b.homeworkView.adapter = adapter
b.homeworkView.visibility = View.VISIBLE
b.homeworkNoData.visibility = View.GONE
} else {
b.homeworkView.visibility = View.GONE
b.homeworkNoData.visibility = View.VISIBLE
}
})
}
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2019-11-4
*/
package pl.szczodrzynski.edziennik.ui.modules.homework
import android.os.AsyncTask
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
import pl.szczodrzynski.edziennik.data.db.modules.metadata.MetadataDao
import pl.szczodrzynski.edziennik.ui.base.BasePresenter
import javax.inject.Inject
class HomeworkPresenter @Inject constructor(
private val metadataDao: MetadataDao
) : BasePresenter<HomeworkView>() {
override fun onAttachView(view: HomeworkView) {
super.onAttachView(view)
view.initView()
}
fun onPageSelected(position: Int) {
view?.setPageSelection(position)
}
fun onAddEventClick() {
view?.apply {
closeBottomSheet()
showAddHomeworkDialog()
}
}
fun onMarkAsReadClick() {
view?.apply {
closeBottomSheet()
AsyncTask.execute {
metadataDao.setAllSeen(App.profileId, Metadata.TYPE_HOMEWORK, true)
}
showMessage(markAsReadSuccessString)
}
}
fun onHomeworkAddFabClick() {
view?.showAddHomeworkDialog()
}
}

View File

@ -0,0 +1,20 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2019-11-4
*/
package pl.szczodrzynski.edziennik.ui.modules.homework
import pl.szczodrzynski.edziennik.ui.base.BaseView
interface HomeworkView : BaseView {
val markAsReadSuccessString: String
fun initView()
fun closeBottomSheet()
fun showAddHomeworkDialog()
fun setPageSelection(position: Int)
}

View File

@ -0,0 +1,111 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2019-11-4
*/
package pl.szczodrzynski.edziennik.ui.modules.homework.list
import android.content.res.Resources
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.graphics.drawable.Drawable
import android.os.AsyncTask
import android.view.LayoutInflater
import android.view.View.GONE
import android.view.View.VISIBLE
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.RecyclerView
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull
import pl.szczodrzynski.edziennik.data.db.modules.metadata.MetadataDao
import pl.szczodrzynski.edziennik.databinding.RowHomeworkItemBinding
import pl.szczodrzynski.edziennik.utils.Utils.bs
import pl.szczodrzynski.edziennik.utils.models.Date
import javax.inject.Inject
import kotlin.math.abs
class HomeworkListAdapter @Inject constructor(
private val metadataDao: MetadataDao
) : RecyclerView.Adapter<HomeworkListAdapter.ViewHolder>() {
val homeworkList: MutableList<EventFull> = mutableListOf()
lateinit var onItemEditClick: (homework: EventFull) -> Unit
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val b: RowHomeworkItemBinding = DataBindingUtil.inflate(inflater, R.layout.row_homework_item, parent, false)
return ViewHolder(b)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val homework = homeworkList[position]
holder.apply {
val diffDaysString = dateDiffString(Date.diffDays(homework.eventDate, Date.getToday()))
b.homeworkItemHomeworkDate.text = getString(R.string.date_relative_format, homework.eventDate.formattedString, diffDaysString)
b.homeworkItemTopic.text = homework.topic
b.homeworkItemSubjectTeacher.text = getString(R.string.homework_subject_teacher_format, bs(homework.subjectLongName), bs(homework.teacherFullName))
b.homeworkItemTeamDate.text = getString(R.string.homework_team_date_format, bs(homework.teamName), Date.fromMillis(homework.addedDate).formattedStringShort)
when {
!homework.seen -> {
b.homeworkItemTopic.apply {
background = getDrawable(R.drawable.bg_rounded_8dp)
background.colorFilter = PorterDuffColorFilter(0x692196f3, PorterDuff.Mode.MULTIPLY)
}
homework.seen = true
AsyncTask.execute {
metadataDao.setSeen(App.profileId, homework, true)
}
}
else -> b.homeworkItemTopic.background = null
}
b.homeworkItemEdit.apply {
visibility = if (homework.addedManually) VISIBLE else GONE
setOnClickListener { onItemEditClick(homework) }
}
b.homeworkItemSharedBy.apply {
when {
homework.sharedBy == null -> visibility = GONE
homework.sharedByName != null -> text = getString(R.string.event_shared_by_format,
when (homework.sharedBy == "self") {
true -> getString(R.string.event_shared_by_self)
else -> homework.sharedByName
})
}
}
}
}
override fun getItemCount() = homeworkList.size
class ViewHolder(val b: RowHomeworkItemBinding) : RecyclerView.ViewHolder(b.root) {
fun getString(resId: Int): String = itemView.context.getString(resId)
fun getString(resId: Int, vararg formatArgs: Any): String = itemView.context.getString(resId, *formatArgs)
fun getDrawable(resId: Int): Drawable? = ContextCompat.getDrawable(itemView.context, resId)
val resources: Resources get() = itemView.context.resources
fun dateDiffString(diff: Int): String {
return when {
diff > 0 -> when (diff) {
1 -> getString(R.string.tomorrow)
2 -> getString(R.string.the_day_after)
else -> resources.getQuantityString(R.plurals.time_till_days, abs(diff), abs(diff))
}
diff < 0 -> when (diff) {
-1 -> getString(R.string.yesterday)
-2 -> getString(R.string.the_day_before)
else -> getString(R.string.ago_format, resources.getQuantityString(R.plurals.time_till_days, abs(diff), abs(diff)))
}
else -> getString(R.string.today)
}
}
}
}

View File

@ -0,0 +1,107 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2019-11-4
*/
package pl.szczodrzynski.edziennik.ui.modules.homework.list
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.lifecycle.Lifecycle
import androidx.recyclerview.widget.LinearLayoutManager
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull
import pl.szczodrzynski.edziennik.databinding.HomeworkListBinding
import pl.szczodrzynski.edziennik.ui.base.BaseFragment
import pl.szczodrzynski.edziennik.ui.dialogs.event.EventManualDialog
import pl.szczodrzynski.edziennik.utils.Themes
import javax.inject.Inject
class HomeworkListFragment : BaseFragment<HomeworkListPresenter>(), HomeworkListView {
private lateinit var activity: MainActivity
private lateinit var b: HomeworkListBinding
@Inject
override lateinit var presenter: HomeworkListPresenter
@Inject
lateinit var app: App
@Inject
lateinit var homeworkAdapter: HomeworkListAdapter
override val viewLifecycle: Lifecycle
get() = lifecycle
companion object {
private const val ARGUMENT_KEY = "homeworkDate"
fun newInstance(homeworkDate: Int) = HomeworkListFragment().apply {
arguments = Bundle().apply { putInt(ARGUMENT_KEY, homeworkDate) }
}
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
presenter.onAttachView(this, arguments?.getInt(ARGUMENT_KEY))
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
activity = (getActivity() as MainActivity?) ?: return null
if (context == null)
return null
context!!.theme.applyStyle(Themes.appTheme, true)
if (app.profile == null)
return inflater.inflate(R.layout.fragment_loading, container, false)
// activity, context and profile is valid
b = HomeworkListBinding.inflate(inflater)
return b.root
}
override fun initView() {
// TODO check if app, activity, b can be null
if (app.profile == null || !isAdded)
return
val layoutManager = LinearLayoutManager(context).apply {
reverseLayout = true
stackFromEnd = true
}
homeworkAdapter.onItemEditClick = presenter::onItemEditClick
b.homeworkView.apply {
setHasFixedSize(true)
this.layoutManager = layoutManager
adapter = homeworkAdapter
}
}
override fun updateData(data: List<EventFull>) {
homeworkAdapter.apply {
homeworkList.apply {
clear()
addAll(data)
}
notifyDataSetChanged()
}
}
override fun showContent(show: Boolean) {
b.homeworkView.visibility = if (show) VISIBLE else GONE
}
override fun showNoData(show: Boolean) {
b.homeworkNoData.visibility = if (show) VISIBLE else GONE
}
override fun showEditHomeworkDialog(homework: EventFull) {
EventManualDialog(context).show(app, homework, null, null, EventManualDialog.DIALOG_HOMEWORK)
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2019-11-4
*/
package pl.szczodrzynski.edziennik.ui.modules.homework.list
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
import pl.szczodrzynski.edziennik.data.db.modules.events.EventDao
import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull
import pl.szczodrzynski.edziennik.ui.base.BasePresenter
import pl.szczodrzynski.edziennik.ui.modules.homework.HomeworkDate
import pl.szczodrzynski.edziennik.utils.models.Date
import javax.inject.Inject
class HomeworkListPresenter @Inject constructor(
private val app: App,
private val eventDao: EventDao
) : BasePresenter<HomeworkListView>() {
fun onAttachView(view: HomeworkListView, homeworkDate: Int?) {
super.onAttachView(view)
view.initView()
loadData(homeworkDate ?: HomeworkDate.CURRENT)
}
private fun loadData(homeworkDate: Int) {
val today = Date.getToday().stringY_m_d
val filter = when (homeworkDate) {
HomeworkDate.CURRENT -> "eventDate > '$today'"
else -> "eventDate <= '$today'"
}
view?.run {
eventDao.getAllByType(App.profileId, Event.TYPE_HOMEWORK, filter)
.observe({ viewLifecycle }, { homeworkList ->
if (app.profile == null) return@observe
if (homeworkList != null && homeworkList.size > 0) {
updateData(homeworkList)
showContent(true)
showNoData(false)
} else {
showContent(false)
showNoData(true)
}
})
}
}
fun onItemEditClick(homework: EventFull) {
view?.showEditHomeworkDialog(homework)
}
}

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2019-11-4
*/
package pl.szczodrzynski.edziennik.ui.modules.homework.list
import androidx.lifecycle.Lifecycle
import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull
import pl.szczodrzynski.edziennik.ui.base.BaseView
interface HomeworkListView : BaseView {
val viewLifecycle: Lifecycle
fun initView()
fun updateData(data: List<EventFull>)
fun showContent(show: Boolean)
fun showNoData(show: Boolean)
fun showEditHomeworkDialog(homework: EventFull)
}

View File

@ -1,116 +0,0 @@
package pl.szczodrzynski.edziennik.ui.modules.login
import android.annotation.SuppressLint
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.util.Base64
import android.webkit.JavascriptInterface
import android.webkit.WebView
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import com.afollestad.materialdialogs.MaterialDialog
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.api.v2.LIBRUS_USER_AGENT
import pl.szczodrzynski.edziennik.utils.Themes
import pl.szczodrzynski.edziennik.utils.Utils.hexFromColorInt
import java.nio.charset.Charset
class LoginLibrusCaptchaActivity : AppCompatActivity() {
companion object {
private const val TAG = "LoginLibrusCaptchaActivity"
}
private lateinit var webView: WebView
private lateinit var dialog: AlertDialog
private lateinit var jsInterface: CaptchaCallbackInterface
@SuppressLint("AddJavascriptInterface", "SetJavaScriptEnabled")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setTheme(Themes.appThemeNoDisplay)
setFinishOnTouchOutside(false)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true)
}
val base64Content = """
PCFET0NUWVBFIGh0bWw+PGh0bWw+PGhlYWQ+PHNjcmlwdCBzcmM9Imh0dHBzOi8vd3d3Lmdvb2ds
ZS5jb20vcmVjYXB0Y2hhL2FwaS5qcz9vbmxvYWQ9cmVhZHkmcmVuZGVyPWV4cGxpY2l0Ij48L3Nj
cmlwdD48L2hlYWQ+PGJvZHk+PGJyPjxjZW50ZXIgaWQ9ImdyIj48L2NlbnRlcj48YnI+PHNjcmlw
dD5mdW5jdGlvbiByZWFkeSgpe2dyZWNhcHRjaGEucmVuZGVyKCdncicse3NpdGVrZXk6JzZMZjQ4
bW9VQUFBQUFCOUNsaGR2SHI0NmdSV1ItQ04zMUNYUVBHMlUnLHRoZW1lOidUSEVNRScsY2FsbGJh
Y2s6ZnVuY3Rpb24oZSl7d2luZG93LmlmLmNhbGxiYWNrKGUpO30sImV4cGlyZWQtY2FsbGJhY2si
OmZ1bmN0aW9uKCl7d2luZG93LmlmLmV4cGlyZWRDYWxsYmFjayhlKTt9LCJlcnJvci1jYWxsYmFj
ayI6ZnVuY3Rpb24oKXt3aW5kb3cuaWYuZXJyb3JDYWxsYmFjayhlKTt9fSk7fTwvc2NyaXB0Pjwv
Ym9keT48L2h0bWw+"""
val backgroundColor = if (Themes.isDark) 0x424242 else 0xffffff
val backgroundColorString = hexFromColorInt(backgroundColor)
val htmlContent = Base64.decode(base64Content, Base64.DEFAULT)
.toString(Charset.defaultCharset())
.replace("COLOR", backgroundColorString, true)
.replace("THEME", if (Themes.isDark) "dark" else "light")
jsInterface = object : CaptchaCallbackInterface {
@JavascriptInterface
override fun callback(recaptchaResponse: String) {
MaterialDialog.Builder(this@LoginLibrusCaptchaActivity)
.title("Captcha checked")
.content("Response: $recaptchaResponse")
.positiveText("OK")
.show()
}
@JavascriptInterface
override fun expiredCallback() {
MaterialDialog.Builder(this@LoginLibrusCaptchaActivity)
.title("Captcha expired")
.content("Captcha expired")
.positiveText("OK")
.show()
}
@JavascriptInterface
override fun errorCallback() {
MaterialDialog.Builder(this@LoginLibrusCaptchaActivity)
.title("Captcha error")
.content("Captcha error")
.positiveText("OK")
.show()
}
}
webView = WebView(this).apply {
//setBackgroundColor((backgroundColor.toLong() or 0xff000000).toInt())
setBackgroundColor(Color.TRANSPARENT)
settings.javaScriptEnabled = true
settings.userAgentString = LIBRUS_USER_AGENT
addJavascriptInterface(jsInterface, "if")
loadDataWithBaseURL("https://portal.librus.pl/rodzina/login/", htmlContent, "text/html", "UTF-8", null)
setLayerType(WebView.LAYER_TYPE_SOFTWARE, null)
}
dialog = MaterialAlertDialogBuilder(this)
.setTitle(R.string.login_librus_captcha_title)
.setView(webView)
.setNegativeButton(R.string.cancel) { dialog, _ ->
dialog.dismiss()
finish()
}
.setCancelable(false)
.show()
}
interface CaptchaCallbackInterface {
@JavascriptInterface
fun callback(recaptchaResponse: String)
@JavascriptInterface
fun expiredCallback()
@JavascriptInterface
fun errorCallback()
}
}

View File

@ -1,24 +0,0 @@
package pl.szczodrzynski.edziennik.utils
import android.content.ComponentName
import android.content.Intent
val appManagerIntentList = listOf(
Intent().setClassName("com.miui.powerkeeper", "com.miui.powerkeeper.ui.HiddenAppsConfigActivity")
.putExtra("packageName", "pl.szczodrzynski.edziennik")
.putExtra("package_label", "Szkolny.eu"),
Intent().setComponent(ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity")),
Intent().setComponent(ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.AutobootManageActivity")),
Intent().setComponent(ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity")),
Intent().setComponent(ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.appcontrol.activity.StartupAppControlActivity")),
Intent().setComponent(ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.startupmgr.ui.StartupNormalAppListActivity")),
Intent().setComponent(ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity")),
Intent().setComponent(ComponentName("com.coloros.safecenter", "com.coloros.safecenter.startupapp.StartupAppListActivity")),
Intent().setComponent(ComponentName("com.oppo.safe", "com.oppo.safe.permission.startup.StartupAppListActivity")),
Intent().setComponent(ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity")),
Intent().setComponent(ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.BgStartUpManager")),
Intent().setComponent(ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity")),
Intent().setComponent(ComponentName("com.samsung.android.lool", "com.samsung.android.sm.ui.battery.BatteryActivity")),
Intent().setComponent(ComponentName("com.htc.pitroad", "com.htc.pitroad.landingpage.activity.LandingPageActivity")),
Intent().setComponent(ComponentName("com.asus.mobilemanager", "com.asus.mobilemanager.MainActivity"))
)

View File

@ -36,46 +36,24 @@
android:layout_height="wrap_content"
android:visibility="gone"
android:orientation="vertical"
tools:visibility="visible"
tools:ignore="HardcodedText">
<com.google.android.material.button.MaterialButton
android:id="@+id/librusCaptchaButton"
style="@style/Widget.MaterialComponents.Button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="Librus Captcha" />
<com.google.android.material.button.MaterialButton
android:id="@+id/runChucker"
style="@style/Widget.MaterialComponents.Button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="Launch Chucker" />
tools:visibility="visible">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
android:layout_height="wrap_content">
<com.google.android.material.button.MaterialButton
android:id="@+id/mobidziennikMessagesSwitch"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Zmień moduł wiadomości" />
<com.google.android.material.button.MaterialButton
android:id="@+id/composeButton"
style="@style/Widget.MaterialComponents.Button"
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="1"
android:text="Compose" />
</LinearLayout>

View File

@ -1,113 +1,116 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
xmlns:tools="http://schemas.android.com/tools">
<com.google.android.material.card.MaterialCardView
android:id="@+id/homeworkItemCard"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:cardElevation="4dp"
app:cardCornerRadius="5dp"
android:background="?selectableItemBackground"
android:paddingLeft="10dp"
android:paddingTop="5dp"
android:paddingRight="10dp"
android:paddingBottom="3dp">
android:orientation="vertical">
<LinearLayout
<com.google.android.material.card.MaterialCardView
android:id="@+id/homeworkItemCard"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="8dp">
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:background="?selectableItemBackground"
android:paddingLeft="10dp"
android:paddingTop="5dp"
android:paddingRight="10dp"
android:paddingBottom="3dp"
app:cardCornerRadius="5dp"
app:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
android:orientation="vertical"
android:padding="8dp">
<TextView
android:id="@+id/homeworkItemHomeworkDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textSize="16sp"
tools:text="homeworkDate"
android:layout_marginEnd="16dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<com.mikepenz.iconics.view.IconicsTextView
android:id="@+id/homeworkItemSharedBy"
<TextView
android:id="@+id/homeworkItemHomeworkDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textSize="16sp"
tools:text="homeworkDate" />
<com.mikepenz.iconics.view.IconicsTextView
android:id="@+id/homeworkItemSharedBy"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:ellipsize="end"
android:gravity="end"
android:maxLines="1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/constraintLayout"
app:layout_constraintTop_toBottomOf="@+id/eventListItemTopic"
tools:text="{cmd-share-variant} przez" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:ellipsize="end"
android:gravity="end"
android:maxLines="1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/constraintLayout"
app:layout_constraintTop_toBottomOf="@+id/eventListItemTopic"
tools:text="{cmd-share-variant} przez" />
</LinearLayout>
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/homeworkItemTopic"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:autoLink="all"
android:paddingBottom="4dp"
android:textIsSelectable="true"
android:textSize="18sp"
tools:text="topic???" />
<TextView
android:id="@+id/homeworkItemTopic"
<com.google.android.material.button.MaterialButton
android:id="@+id/homeworkItemEdit"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:minHeight="0dp"
android:text="@string/homework_edit"
android:visibility="visible" /><!--android:minWidth="0dp"
android:minHeight="0dp"-->
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingBottom="4dp"
android:textSize="18sp"
android:textIsSelectable="true"
android:autoLink="all"
tools:text="topic???" />
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:id="@+id/homeworkItemEdit"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:minHeight="0dp"
android:text="@string/homework_edit"
android:visibility="visible" /><!--android:minWidth="0dp"
android:minHeight="0dp"-->
<TextView
android:id="@+id/homeworkItemSubjectTeacher"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:text="subjectName, teacherName" />
<TextView
android:id="@+id/homeworkItemTeamDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:text="teamName addedDate" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
</com.google.android.material.card.MaterialCardView>
<TextView
android:id="@+id/homeworkItemSubjectTeacher"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:text="subjectName, teacherName" />
<TextView
android:id="@+id/homeworkItemTeamDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:text="teamName addedDate" />
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</LinearLayout>
</layout>

View File

@ -930,7 +930,6 @@
<string name="settings_register_show_teacher_absences_text">Pokazuj nieobecności nauczycieli w Terminarzu</string>
<string name="edziennik_progress_endpoint_school_info">Pobieram informacje o szkole...</string>
<string name="edziennik_progress_endpoint_grades">Pobieranie ocen ucznia...</string>
<string name="edziennik_progress_endpoint_grade_categories">Pobieranie kategorii ocen...</string>
<string name="edziennik_progress_login_template_web">Logowanie do Template WEB...</string>
<string name="edziennik_progress_login_template_api">Logowanie do Template API...</string>
<string name="edziennik_progress_login_mobidziennik_web">Logowanie do MobiDziennika...</string>
@ -984,5 +983,4 @@
<string name="dont_ask_again">Nie pytaj ponownie</string>
<string name="app_manager_open_failed">Nie udało się otworzyć ustawień</string>
<string name="edziennik_notification_api_notify_title">Tworzenie powiadomień</string>
<string name="login_librus_captcha_title">Librus - logowanie</string>
</resources>

View File

@ -5,8 +5,8 @@ buildscript {
kotlin_version = '1.3.50'
release = [
versionName: "3.9.1-dev",
versionCode: 3090100
versionName: "3.1.1",
versionCode: 3010199
]
setup = [
@ -47,7 +47,8 @@ buildscript {
navlib : "e4ad01dc87",
gifdrawable : "1.2.15"
gifdrawable : "1.2.15",
dagger : "2.24"
]
}