-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FEAT] Add timeline widget for android #196
Draft
callasio
wants to merge
14
commits into
main
Choose a base branch
from
195-android-timeline-widget
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
e9b265b
feat: add sample widget
callasio e12d8b1
Revert "feat: add sample widget"
callasio 3650220
fix: delete configuration page & change widget name
callasio c33fcec
feat: impl design for next_lecture
callasio 927ef80
feat: add widgets
callasio 39f4cd7
feat: Modify placeholder for widget preview
callasio 66dc1bf
feat: add widget description
callasio 094df6e
feat: add rounded corner to background
callasio 25e3890
feat: add timetable frame
callasio a540f03
feat: add preview for api level 30 or lower
callasio d69efe2
feat: add timetable block
callasio 01b0a6e
feat: add timetable block color
callasio 06a1c9d
chore: delete timeline file
callasio 7b5f676
Update: main_page.dart
happycastle114 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,49 +1,79 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> | ||
<!-- io.flutter.app.FlutterApplication is an android.app.Application that | ||
|
||
<!-- | ||
io.flutter.app.FlutterApplication is an android.app.Application that | ||
calls FlutterMain.startInitialization(this); in its onCreate method. | ||
In most cases you can leave this as-is, but you if you want to provide | ||
additional functionality it is fine to subclass or reimplement | ||
FlutterApplication and put your custom class here. --> | ||
<uses-permission | ||
android:name="android.permission.INTERNET"/> | ||
FlutterApplication and put your custom class here. | ||
--> | ||
<uses-permission android:name="android.permission.INTERNET" /> | ||
<uses-permission | ||
android:name="android.permission.WRITE_EXTERNAL_STORAGE" | ||
android:maxSdkVersion="28"/> | ||
<uses-permission | ||
android:name="android.permission.READ_EXTERNAL_STORAGE"/> | ||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> | ||
android:maxSdkVersion="28" /> | ||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> | ||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> | ||
|
||
<application | ||
android:name="${applicationName}" | ||
android:label="OTL" | ||
android:icon="@mipmap/ic_launcher" | ||
android:allowBackup="true" | ||
android:fullBackupContent="true"> | ||
android:fullBackupContent="true" | ||
android:icon="@mipmap/ic_launcher" | ||
android:label="OTL"> | ||
<receiver | ||
android:name=".TimetableWidget" | ||
android:exported="false"> | ||
<intent-filter> | ||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> | ||
</intent-filter> | ||
|
||
<meta-data | ||
android:name="android.appwidget.provider" | ||
android:resource="@xml/timetable_widget_info" /> | ||
</receiver> | ||
<receiver | ||
android:name=".NextLectureWidget" | ||
android:exported="false"> | ||
<intent-filter> | ||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> | ||
</intent-filter> | ||
|
||
<meta-data | ||
android:name="android.appwidget.provider" | ||
android:resource="@xml/next_lecture_widget_info" /> | ||
</receiver> | ||
|
||
<activity | ||
android:name=".MainActivity" | ||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" | ||
android:exported="true" | ||
android:hardwareAccelerated="true" | ||
android:launchMode="singleTop" | ||
android:screenOrientation="portrait" | ||
android:theme="@style/LaunchTheme" | ||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" | ||
android:hardwareAccelerated="true" | ||
android:windowSoftInputMode="adjustResize" | ||
android:exported="true"> | ||
android:windowSoftInputMode="adjustResize"> | ||
<intent-filter> | ||
<action android:name="android.intent.action.MAIN"/> | ||
<category android:name="android.intent.category.LAUNCHER"/> | ||
<action android:name="android.intent.action.MAIN" /> | ||
|
||
<category android:name="android.intent.category.LAUNCHER" /> | ||
</intent-filter> | ||
</activity> | ||
<service | ||
android:name="com.kuku.channel_talk_flutter.PushInterceptService" | ||
android:exported="true" | ||
> | ||
|
||
<service | ||
android:name="com.kuku.channel_talk_flutter.PushInterceptService" | ||
android:exported="true"> | ||
<intent-filter> | ||
<action android:name="com.google.firebase.MESSAGING_EVENT"/> | ||
<action android:name="com.google.firebase.MESSAGING_EVENT" /> | ||
</intent-filter> | ||
</service> | ||
<!-- Don't delete the meta-data below. | ||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> | ||
<!-- | ||
Don't delete the meta-data below. | ||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java | ||
--> | ||
<meta-data | ||
android:name="flutterEmbedding" | ||
android:value="2"/> | ||
android:value="2" /> | ||
</application> | ||
|
||
</manifest> |
48 changes: 48 additions & 0 deletions
48
android/app/src/main/java/org/sparcs/otlplus/NextLectureWidget.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package org.sparcs.otlplus | ||
|
||
import android.appwidget.AppWidgetManager | ||
import android.appwidget.AppWidgetProvider | ||
import android.content.Context | ||
import android.widget.RemoteViews | ||
import org.sparcs.otlplus.api.NextLectureData | ||
|
||
/** | ||
* Implementation of App Widget functionality. | ||
*/ | ||
|
||
class NextLectureWidget : AppWidgetProvider() { | ||
override fun onUpdate( | ||
context: Context, | ||
appWidgetManager: AppWidgetManager, | ||
appWidgetIds: IntArray | ||
) { | ||
// There may be multiple widgets active, so update all of them | ||
for (appWidgetId in appWidgetIds) { | ||
updateNextLectureWidget(context, appWidgetManager, appWidgetId) | ||
} | ||
} | ||
|
||
override fun onEnabled(context: Context) { | ||
// Enter relevant functionality for when the first widget is created | ||
} | ||
|
||
override fun onDisabled(context: Context) { | ||
// Enter relevant functionality for when the last widget is disabled | ||
} | ||
} | ||
|
||
internal fun updateNextLectureWidget( | ||
context: Context, | ||
appWidgetManager: AppWidgetManager, | ||
appWidgetId: Int | ||
) { | ||
// Construct the RemoteViews object | ||
RemoteViews(context.packageName, R.layout.next_lecture_widget).let { | ||
it.setTextViewText(R.id.nextLectureDate, NextLectureData.nextLectureDate) | ||
it.setTextViewText(R.id.nextLectureName, NextLectureData.nextLectureName) | ||
it.setTextViewText(R.id.nextLecturePlace, NextLectureData.nextLecturePlace) | ||
it.setTextViewText(R.id.nextLectureProfessor, NextLectureData.nextLectureProfessor) | ||
// Instruct the widget manager to update the widget | ||
appWidgetManager.updateAppWidget(appWidgetId, it) | ||
} | ||
} |
112 changes: 112 additions & 0 deletions
112
android/app/src/main/java/org/sparcs/otlplus/TimetableWidget.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package org.sparcs.otlplus | ||
|
||
import android.annotation.SuppressLint | ||
import android.appwidget.AppWidgetManager | ||
import android.appwidget.AppWidgetProvider | ||
import android.content.Context | ||
import android.util.TypedValue | ||
import android.widget.RemoteViews | ||
import org.sparcs.otlplus.api.Lecture | ||
import org.sparcs.otlplus.api.LocalTime | ||
import org.sparcs.otlplus.api.TimetableData | ||
import org.sparcs.otlplus.api.WeekDays | ||
import org.sparcs.otlplus.constants.BlockColor | ||
|
||
val timeTableColumns = listOf( | ||
R.id.time_table_column_1, | ||
R.id.time_table_column_2, | ||
R.id.time_table_column_3, | ||
R.id.time_table_column_4, | ||
R.id.time_table_column_5, | ||
) | ||
|
||
data class TimeTableElement( | ||
val length: Float, | ||
val lecture: Lecture? | ||
) | ||
|
||
/** | ||
* Implementation of App Widget functionality. | ||
*/ | ||
class TimetableWidget : AppWidgetProvider() { | ||
override fun onUpdate( | ||
context: Context, | ||
appWidgetManager: AppWidgetManager, | ||
appWidgetIds: IntArray | ||
) { | ||
// There may be multiple widgets active, so update all of them | ||
for (appWidgetId in appWidgetIds) { | ||
updateTimetableWidget(context, appWidgetManager, appWidgetId) | ||
} | ||
} | ||
|
||
override fun onEnabled(context: Context) { | ||
// Enter relevant functionality for when the first widget is created | ||
} | ||
|
||
override fun onDisabled(context: Context) { | ||
// Enter relevant functionality for when the last widget is disabled | ||
} | ||
} | ||
|
||
@SuppressLint("NewApi") | ||
internal fun updateTimetableWidget( | ||
context: Context, | ||
appWidgetManager: AppWidgetManager, | ||
appWidgetId: Int | ||
) { | ||
val views = RemoteViews(context.packageName, R.layout.timetable_widget) | ||
|
||
for (timetableColumn in timeTableColumns) { | ||
views.removeAllViews(timetableColumn) | ||
} | ||
|
||
val weekTimetable = createTimeTable(TimetableData.lectures) | ||
|
||
for ((weekday, dayTimetable) in weekTimetable.withIndex()) { | ||
for (timeTableElement in dayTimetable) { | ||
val blockView = when(timeTableElement.lecture) { | ||
null -> RemoteViews(context.packageName, R.layout.blank_view) | ||
else -> RemoteViews(context.packageName, BlockColor.getLayout(timeTableElement.lecture)).apply { | ||
setTextViewText(R.id.timetable_block_lecture_name, timeTableElement.lecture.name) | ||
} | ||
} | ||
|
||
blockView.setViewLayoutHeight( | ||
R.id.timetable_block_root, | ||
timeTableElement.length * 36, | ||
TypedValue.COMPLEX_UNIT_DIP) | ||
|
||
views.addView(timeTableColumns[weekday], blockView) | ||
} | ||
} | ||
|
||
// Instruct the widget manager to update the widget | ||
appWidgetManager.updateAppWidget(appWidgetId, views) | ||
} | ||
|
||
fun createTimeTable(lectures: List<Lecture>): List<List<TimeTableElement>> { | ||
val timetable = List(5) { mutableListOf<TimeTableElement>() } | ||
|
||
for (dayIndex in WeekDays.entries.toTypedArray().indices) { | ||
val day = WeekDays.entries[dayIndex] | ||
|
||
val dailyLectures = lectures.flatMap { lecture -> | ||
lecture.timeBlocks.filter { it.weekday == day }.map { it to lecture } | ||
}.sortedBy { it.first.start.hoursFloat } | ||
|
||
var currentTime = LocalTime(9, 0) | ||
|
||
for ((timeBlock, lecture) in dailyLectures) { | ||
if (timeBlock.start.hoursFloat > currentTime.hoursFloat) { | ||
val freeTimeLength = timeBlock.start.hoursFloat - currentTime.hoursFloat | ||
timetable[dayIndex].add(TimeTableElement(freeTimeLength, null)) | ||
} | ||
val lectureLength = timeBlock.end.hoursFloat - timeBlock.start.hoursFloat | ||
timetable[dayIndex].add(TimeTableElement(lectureLength, lecture)) | ||
currentTime = timeBlock.end | ||
} | ||
} | ||
|
||
return timetable | ||
} |
31 changes: 31 additions & 0 deletions
31
android/app/src/main/java/org/sparcs/otlplus/api/Lecture.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package org.sparcs.otlplus.api | ||
|
||
enum class WeekDays { | ||
Mon, | ||
Tue, | ||
Wed, | ||
Thu, | ||
Fri, | ||
} | ||
|
||
data class LocalTime( | ||
val hours: Int, | ||
val minutes: Int, | ||
) { | ||
val hoursFloat: Float | ||
get() = hours + minutes / 60f | ||
} | ||
|
||
data class TimeBlock( | ||
val weekday: WeekDays, | ||
val start: LocalTime, | ||
val end: LocalTime | ||
) | ||
|
||
data class Lecture( | ||
val name: String, | ||
val timeBlocks: List<TimeBlock>, | ||
val place: String, | ||
val professor: String, | ||
val course: Int, | ||
) |
15 changes: 15 additions & 0 deletions
15
android/app/src/main/java/org/sparcs/otlplus/api/NextLectureData.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package org.sparcs.otlplus.api | ||
|
||
object NextLectureData { // TODO: Get data using api | ||
val nextLectureDate | ||
get() = "다음주 월요일" | ||
|
||
val nextLectureName | ||
get() = "일반물리학" | ||
|
||
val nextLecturePlace | ||
get() = "(E11)창의학습관 311" | ||
|
||
val nextLectureProfessor | ||
get() = "김교수" | ||
} |
43 changes: 43 additions & 0 deletions
43
android/app/src/main/java/org/sparcs/otlplus/api/TimetableData.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package org.sparcs.otlplus.api | ||
|
||
object TimetableData { | ||
val lectures: List<Lecture> | ||
get() = listOf( | ||
Lecture( | ||
name = "프로그래밍 기초", | ||
place = "(E11)창의학습관 308", | ||
professor = "김교수", | ||
timeBlocks = listOf( | ||
TimeBlock( | ||
weekday = WeekDays.Mon, | ||
start = LocalTime(9, 0), | ||
end = LocalTime(12, 0), | ||
), | ||
TimeBlock( | ||
weekday = WeekDays.Wed, | ||
start = LocalTime(10, 30), | ||
end = LocalTime(12, 0), | ||
), | ||
), | ||
course = 317 | ||
), | ||
Lecture( | ||
name = "지속가능 사회 인프라 시스템과 환경의 이해", | ||
place = "(E11) 창의학습관 208", | ||
professor = "김교수", | ||
timeBlocks = listOf( | ||
TimeBlock( | ||
weekday = WeekDays.Mon, | ||
start = LocalTime(16, 0), | ||
end = LocalTime(17, 30), | ||
), | ||
TimeBlock( | ||
weekday = WeekDays.Wed, | ||
start = LocalTime(16, 0), | ||
end = LocalTime(17, 30), | ||
), | ||
), | ||
course = 100 | ||
) | ||
) | ||
} | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@happycastle114 저 이 부분 API 불러오기 하면 되는데 일단 남겨놓겠습니다 담에 동방 가서 마무리할게요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
넹 한번 저도 확인해볼게요