[UI] Add teachers list feature. (#94)

* Add teachers list feature

* Fix

* some fixes

* Auto stash before merge of "develop" and "origin/develop"

* Add teachers list feature

* Fix

* some fixes

* [UI] Fix updating badges crashing with expanded items.

* Add support for fetching teachers from vulcan, fix some code

* Update app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Teacher.kt

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

* Update some code

* Update app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

* Update app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Teacher.kt

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

* Update app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

* Update app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

* Update app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeTeachers.kt

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

* Update app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Teacher.kt

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

* Update app/src/main/java/pl/szczodrzynski/edziennik/data/db/migration/Migration96.kt

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

* Update app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

* Update app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

* Update app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeTeachers.kt

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

* Update app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

* Update app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

* Update app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

* Update app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

* Optimize code

* Fix loadTarget algorithm

* Apply suggestions from code review

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

* Update app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
This commit is contained in:
Antoni Czaplicki 2021-10-18 23:46:39 +02:00 committed by GitHub
parent 74b766f18a
commit 2807659da3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 676 additions and 266 deletions

View File

@ -0,0 +1,6 @@
<component name="CopyrightManager">
<copyright>
<option name="notice" value="Copyright (c) Antoni Czaplicki &amp;#36;{today.year}-&amp;#36;{today.month}-&amp;#36;{today.day}. " />
<option name="myName" value="Antoni" />
</copyright>
</component>

View File

@ -44,6 +44,8 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.gson.*
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import com.mikepenz.iconics.typeface.IIcon
import com.mikepenz.materialdrawer.holder.StringHolder
import im.wangchao.mhttp.Response
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
@ -59,6 +61,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
import pl.szczodrzynski.edziennik.data.db.entity.Team
import pl.szczodrzynski.edziennik.utils.models.Time
import pl.szczodrzynski.navlib.ImageHolder
import java.io.InterruptedIOException
import java.io.PrintWriter
import java.io.StringWriter
@ -862,6 +865,8 @@ fun @receiver:DrawableRes Int.resolveDrawable(context: Context): Drawable {
}
}
fun @receiver:StringRes Int.resolveString(context: Context) = context.getString(this)
fun View.findParentById(targetId: Int): View? {
if (id == targetId) {
return this
@ -1371,3 +1376,7 @@ fun CharSequence.getWordBounds(position: Int, onlyInWord: Boolean = false): Pair
}
infix fun Int.hasSet(what: Int) = this and what == what
fun Int.toStringHolder() = StringHolder(this)
fun CharSequence.toStringHolder() = StringHolder(this)
fun IIcon.toImageHolder() = ImageHolder(this)

File diff suppressed because it is too large Load Diff

View File

@ -109,6 +109,7 @@ const val VULCAN_HEBE_ENDPOINT_PUSH_ALL = "api/mobile/push/all"
const val VULCAN_HEBE_ENDPOINT_TIMETABLE = "api/mobile/schedule"
const val VULCAN_HEBE_ENDPOINT_TIMETABLE_CHANGES = "api/mobile/schedule/changes"
const val VULCAN_HEBE_ENDPOINT_ADDRESSBOOK = "api/mobile/addressbook"
const val VULCAN_HEBE_ENDPOINT_TEACHERS = "api/mobile/teacher"
const val VULCAN_HEBE_ENDPOINT_EXAMS = "api/mobile/exam"
const val VULCAN_HEBE_ENDPOINT_GRADES = "api/mobile/grade"
const val VULCAN_HEBE_ENDPOINT_GRADE_SUMMARY = "api/mobile/grade/summary"

View File

@ -21,6 +21,7 @@ const val ENDPOINT_VULCAN_HEBE_NOTICES = 3070
const val ENDPOINT_VULCAN_HEBE_ATTENDANCE = 3080
const val ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX = 3090
const val ENDPOINT_VULCAN_HEBE_MESSAGES_SENT = 3100
const val ENDPOINT_VULCAN_HEBE_TEACHERS = 3110
const val ENDPOINT_VULCAN_HEBE_LUCKY_NUMBER = 3200
val VulcanFeatures = listOf(
@ -83,6 +84,7 @@ val VulcanFeatures = listOf(
Feature(LOGIN_TYPE_VULCAN, FEATURE_ALWAYS_NEEDED, listOf(
ENDPOINT_VULCAN_HEBE_MAIN to LOGIN_METHOD_VULCAN_HEBE,
ENDPOINT_VULCAN_HEBE_ADDRESSBOOK to LOGIN_METHOD_VULCAN_HEBE
ENDPOINT_VULCAN_HEBE_ADDRESSBOOK to LOGIN_METHOD_VULCAN_HEBE,
ENDPOINT_VULCAN_HEBE_TEACHERS to LOGIN_METHOD_VULCAN_HEBE
), listOf(LOGIN_METHOD_VULCAN_HEBE))
)

View File

@ -27,6 +27,7 @@ class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) {
ENDPOINT_VULCAN_HEBE_NOTICES,
ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX,
ENDPOINT_VULCAN_HEBE_MESSAGES_SENT,
ENDPOINT_VULCAN_HEBE_TEACHERS,
ENDPOINT_VULCAN_HEBE_LUCKY_NUMBER
)
@ -103,9 +104,13 @@ class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) {
VulcanHebePushConfig(data, lastSync, onSuccess)
}
ENDPOINT_VULCAN_HEBE_ADDRESSBOOK -> {
data.startProgress(R.string.edziennik_progress_endpoint_teachers)
data.startProgress(R.string.edziennik_progress_endpoint_addressbook)
VulcanHebeAddressbook(data, lastSync, onSuccess)
}
ENDPOINT_VULCAN_HEBE_TEACHERS -> {
data.startProgress(R.string.edziennik_progress_endpoint_teachers)
VulcanHebeTeachers(data, lastSync, onSuccess)
}
ENDPOINT_VULCAN_HEBE_TIMETABLE -> {
data.startProgress(R.string.edziennik_progress_endpoint_timetable)
VulcanHebeTimetable(data, lastSync, onSuccess)

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) Antoni Czaplicki 2021-10-15.
*/
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
import pl.szczodrzynski.edziennik.DAY
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_TEACHERS
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_TEACHERS
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe
import pl.szczodrzynski.edziennik.getString
class VulcanHebeTeachers(
override val data: DataVulcan,
override val lastSync: Long?,
val onSuccess: (endpointId: Int) -> Unit,
) : VulcanHebe(data, lastSync) {
companion object {
const val TAG = "VulcanHebeTeachers"
}
init {
apiGetList(
TAG,
VULCAN_HEBE_ENDPOINT_TEACHERS,
HebeFilterType.BY_PERIOD,
lastSync = lastSync,
) { list, _ ->
list.forEach { person ->
val name = person.getString("Name")
val surname = person.getString("Surname")
val displayName = person.getString("DisplayName")
val subjectName = person.getString("Description") ?: return@apiGetList
val teacher = data.getTeacherByFirstLast(
name?.plus(" ")?.plus(surname) ?: displayName ?: return@forEach
)
teacher.addSubject(data.getSubject(null, subjectName).id)
}
data.setSyncNext(ENDPOINT_VULCAN_HEBE_TEACHERS, 2 * DAY)
onSuccess(ENDPOINT_VULCAN_HEBE_TEACHERS)
}
}
}

View File

@ -43,7 +43,7 @@ import pl.szczodrzynski.edziennik.data.db.migration.*
LibrusLesson::class,
TimetableManual::class,
Metadata::class
], version = 95)
], version = 96)
@TypeConverters(
ConverterTime::class,
ConverterDate::class,
@ -181,6 +181,7 @@ abstract class AppDb : RoomDatabase() {
Migration93(),
Migration94(),
Migration95(),
Migration96(),
).allowMainThreadQueries().build()
}
}

View File

@ -9,14 +9,11 @@ import android.graphics.Bitmap
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Ignore
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.fixName
import pl.szczodrzynski.edziennik.getNameInitials
import pl.szczodrzynski.edziennik.join
import pl.szczodrzynski.edziennik.*
import java.util.*
@Entity(tableName = "teachers",
primaryKeys = ["profileId", "teacherId"])
primaryKeys = ["profileId", "teacherId"])
open class Teacher {
companion object {
const val TYPE_TEACHER = 0 // 1
@ -26,6 +23,7 @@ open class Teacher {
const val TYPE_SECRETARIAT = 4 // 16
const val TYPE_PRINCIPAL = 5 // 32
const val TYPE_SCHOOL_ADMIN = 6 // 64
// not teachers
const val TYPE_SPECIALIST = 7 // 128
const val TYPE_SUPER_ADMIN = 10 // 1024
@ -36,7 +34,8 @@ open class Teacher {
const val TYPE_OTHER = 24 // 16777216
const val IS_TEACHER_MASK = 127
val types: List<Int> by lazy { listOf(
val types: List<Int> by lazy {
listOf(
TYPE_TEACHER,
TYPE_EDUCATOR,
TYPE_PEDAGOGUE,
@ -51,7 +50,8 @@ open class Teacher {
TYPE_PARENTS_COUNCIL,
TYPE_SCHOOL_PARENTS_COUNCIL,
TYPE_OTHER
) }
)
}
fun typeName(c: Context, type: Int, typeDescription: String? = null): String {
val suffix = typeDescription?.let { " ($typeDescription)" } ?: ""
@ -94,6 +94,9 @@ open class Teacher {
@ColumnInfo(name = "teacherTypeDescription")
var typeDescription: String? = null
@ColumnInfo(name = "teacherSubjects")
var subjects = mutableListOf<Long>()
fun isType(checkingType: Int): Boolean {
return type and (1 shl checkingType) >= 1
}
@ -105,6 +108,8 @@ open class Teacher {
type = type or (1 shl i)
}
fun addSubject(subjectId: Long) = subjects.add(subjectId)
fun unsetTeacherType(i: Int) {
type = type and (1 shl i).inv()
}
@ -128,6 +133,7 @@ open class Teacher {
*/
@Ignore
var recipientDisplayName: CharSequence? = null
/**
* Used in Message composing - determining the priority
* of search result, based on the search phrase match
@ -142,8 +148,6 @@ open class Teacher {
this.id = id
}
@Ignore
constructor(profileId: Int, id: Long, name: String, surname: String) {
this.profileId = profileId
@ -170,6 +174,7 @@ open class Teacher {
this.surname = it.surname
this.type = it.type
this.typeDescription = it.typeDescription
this.subjects = it.subjects
this.image = it.image
this.recipientDisplayName = it.recipientDisplayName
}
@ -195,6 +200,7 @@ open class Teacher {
", name='" + name + '\'' +
", surname='" + surname + '\'' +
", type=" + dumpType() +
", subjects=" + subjects.joinToString() +
", typeDescription='" + typeDescription + '\'' +
'}'
}

View File

@ -0,0 +1,15 @@
/*
* Copyright (c) Antoni Czaplicki 2021-10-17.
*/
package pl.szczodrzynski.edziennik.data.db.migration
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
class Migration96 : Migration(95, 96) {
override fun migrate(database: SupportSQLiteDatabase) {
// teachers - associated subjects list
database.execSQL("ALTER TABLE teachers ADD COLUMN teacherSubjects TEXT NOT NULL;")
}
}

View File

@ -30,7 +30,7 @@ class MessagesComposeSuggestionAdapter(
private val comparator by lazy { Comparator { o1: Teacher, o2: Teacher -> o1.recipientWeight - o2.recipientWeight } }
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val listItem = convertView ?: LayoutInflater.from(context).inflate(R.layout.messages_compose_suggestion_item, parent, false)
val listItem = convertView ?: LayoutInflater.from(context).inflate(R.layout.teacher_item, parent, false)
val teacher = teacherList[position]
val name = listItem.findViewById<TextView>(R.id.name)

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) Antoni Czaplicki 2021-10-15.
*/
package pl.szczodrzynski.edziennik.ui.modules.teachers
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
import pl.szczodrzynski.edziennik.databinding.TeacherItemBinding
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesUtils.getProfileImage
import pl.szczodrzynski.edziennik.utils.BetterLink
import kotlin.coroutines.CoroutineContext
class TeachersAdapter(
private val activity: AppCompatActivity,
val onItemClick: ((item: Teacher) -> Unit)? = null,
) : RecyclerView.Adapter<TeachersAdapter.ViewHolder>(), CoroutineScope {
companion object {
private const val TAG = "TeachersAdapter"
}
private val app = activity.applicationContext as App
// optional: place the manager here
private val job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
var items = listOf<Teacher>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(activity)
val view = TeacherItemBinding.inflate(inflater, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = items[position]
val b = holder.b
b.name.text = item.fullName
b.image.setImageBitmap(item.image?: getProfileImage(48, 24, 16, 12, 1, item.fullName))
var role = item.getTypeText(activity)
if (item.subjects.isNotNullNorEmpty()) {
val subjects = item.subjects.map { App.db.subjectDao().getByIdNow(App.profileId, it).longName }
role = role.plus(": ").plus(subjects.joinToString())
}
b.type.text = role
item.fullName.let { name ->
BetterLink.attach(
b.name,
teachers = mapOf(item.id to name)
)
}
}
override fun getItemCount() = items.size
class ViewHolder(val b: TeacherItemBinding) : RecyclerView.ViewHolder(b.root)
}

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) Antoni Czaplicki 2021-10-15.
*/
package pl.szczodrzynski.edziennik.ui.modules.teachers
import android.app.Activity
import android.content.Intent
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.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.databinding.TeachersListFragmentBinding
import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration
import pl.szczodrzynski.edziennik.utils.Utils
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem
import kotlin.coroutines.CoroutineContext
class TeachersListFragment : Fragment(), CoroutineScope {
companion object {
private const val TAG = "TeachersListFragment"
}
private lateinit var app: App
private lateinit var activity: MainActivity
private lateinit var b: TeachersListFragmentBinding
private val job: Job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
activity = (getActivity() as MainActivity?) ?: return null
context ?: return null
app = activity.application as App
b = TeachersListFragmentBinding.inflate(inflater)
return b.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { startCoroutineTimer(100L) {
if (!isAdded) return@startCoroutineTimer
val adapter = TeachersAdapter(activity)
app.db.teacherDao().getAllTeachers(App.profileId).observe(this@TeachersListFragment, Observer { items ->
if (!isAdded) return@Observer
// load & configure the adapter
adapter.items = items
if (items.isNotNullNorEmpty() && b.list.adapter == null) {
b.list.adapter = adapter
b.list.apply {
setHasFixedSize(true)
layoutManager = LinearLayoutManager(context)
addItemDecoration(SimpleDividerItemDecoration(context))
}
}
adapter.notifyDataSetChanged()
// show/hide relevant views
b.progressBar.isVisible = false
if (items.isNullOrEmpty()) {
b.list.isVisible = false
b.noData.isVisible = true
} else {
b.list.isVisible = true
b.noData.isVisible = false
}
})
}}
}

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) Antoni Czaplicki 2021-10-15.
-->
<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">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/noData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:drawablePadding="16dp"
android:fontFamily="sans-serif-light"
android:gravity="center"
android:padding="16dp"
android:text="@string/teachers_no_data"
android:textSize="24sp"
android:visibility="gone"
app:drawableTopCompat="@drawable/ic_archive"
tools:visibility="visible" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
tools:listitem="@layout/teacher_item"
tools:visibility="visible" />
</FrameLayout>
</layout>

View File

@ -656,6 +656,7 @@
<string name="menu_message">Nachricht</string>
<string name="menu_message_compose">Schreiben Sie eine Nachricht</string>
<string name="menu_messages">Nachrichten</string>
<string name="menu_more">Mehr</string>
<string name="menu_notices">Verhalten</string>
<string name="menu_notifications">Benachrichtigungen</string>
<string name="menu_remove_notifications">Löschen</string>
@ -1108,6 +1109,7 @@
<string name="teacher_super_admin">Administrator / Superadministrator</string>
<string name="teacher_teacher">Lehrer</string>
<string name="teachers_browse_category">Kategorie durchsuchen</string>
<string name="teachers_no_data">Keine Lehrer.</string>
<string name="the_day_after">Übermorgen</string>
<string name="the_day_before">Vorgestern</string>
<string name="theme_amber">Bernstein</string>
@ -1236,4 +1238,6 @@
<string name="login_summary_account_parent">(Elternteil)</string>
<string name="settings_about_contributors_text">Anwendungsentwickler</string>
<string name="settings_about_contributors_subtext">Liste der Szkolny-Entwickler</string>
<string name="menu_teachers">Lehrer</string>
<string name="edziennik_progress_endpoint_addressbook">Addressbuch herunterladen…</string>
</resources>

View File

@ -658,6 +658,7 @@
<string name="menu_message">Message</string>
<string name="menu_message_compose">Compose</string>
<string name="menu_messages">Messages</string>
<string name="menu_more">More</string>
<string name="menu_notices">Behaviour</string>
<string name="menu_notifications">Notifications</string>
<string name="menu_remove_notifications">Clear</string>
@ -1110,6 +1111,7 @@
<string name="teacher_super_admin">SuperAdmin</string>
<string name="teacher_teacher">Teacher</string>
<string name="teachers_browse_category">Browse category</string>
<string name="teachers_no_data">No teachers.</string>
<string name="the_day_after">overmorrow</string>
<string name="the_day_before">the day before yesterday</string>
<string name="theme_amber">Amber</string>
@ -1372,4 +1374,6 @@
<string name="permissions_generate_timetable">In order to be able to save the generated timetable, you must grant access rights to the device\'s memory.\n\nClick OK to grant permissions.</string>
<string name="login_summary_account_child">(Child)</string>
<string name="login_summary_account_parent">(Parent)</string>
<string name="menu_teachers">Teachers</string>
<string name="edziennik_progress_endpoint_addressbook">Syncing addressbook…</string>
</resources>

View File

@ -301,6 +301,7 @@
<string name="edziennik_notification_api_text">Dzięki niej, aplikacja Szkolny.eu może synchronizować dane z e-dziennikiem. Możesz ją zamknąć, ponieważ w tej chwili nic nie robi.</string>
<string name="edziennik_notification_api_title">Usługa synchronizacji</string>
<string name="edziennik_progress_endpoint_account_details">Pobieranie szczegółów konta…</string>
<string name="edziennik_progress_endpoint_addressbook">Pobieranie listy odbiorców…</string>
<string name="edziennik_progress_endpoint_announcements">Pobieranie ogłoszeń szkolnych…</string>
<string name="edziennik_progress_endpoint_attendance">Pobieranie frekwencji ucznia…</string>
<string name="edziennik_progress_endpoint_attendance_types">Pobieranie kategorii obecności…</string>
@ -708,6 +709,7 @@
<string name="menu_message">Wiadomość</string>
<string name="menu_message_compose">Napisz wiadomość</string>
<string name="menu_messages">Wiadomości</string>
<string name="menu_more">Więcej</string>
<string name="menu_notices">Zachowanie</string>
<string name="menu_notifications">Powiadomienia</string>
<string name="menu_remove_notifications">Usuń wszystkie</string>
@ -716,6 +718,7 @@
<string name="menu_settings">Ustawienia</string>
<string name="menu_sync">Synchronizuj</string>
<string name="menu_sync_all">Synchronizuj wszystkie</string>
<string name="menu_teachers">Nauczyciele</string>
<string name="menu_template">Szablon</string>
<string name="menu_timetable">Plan lekcji</string>
<string name="menu_timetable_manual">Edytor planu lekcji</string>
@ -1180,6 +1183,7 @@
<string name="teacher_super_admin">Administrator / SuperAdministrator</string>
<string name="teacher_teacher">Nauczyciel</string>
<string name="teachers_browse_category">Przeglądaj kategorię</string>
<string name="teachers_no_data">Brak nauczycieli.</string>
<string name="the_day_after">pojutrze</string>
<string name="the_day_before">przedwczoraj</string>
<string name="theme_amber">Bursztynowy</string>