Skip to content

Commit 9c0b116

Browse files
committed
solve bug 0000397
1 parent a7a0f91 commit 9c0b116

File tree

21 files changed

+563
-90
lines changed

21 files changed

+563
-90
lines changed

app/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,15 @@ dependencies {
7979
implementation 'com.github.angads25:filepicker:1.1.1'
8080
implementation 'com.github.takusemba:spotlight:1.8.0'
8181
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0-alpha'
82+
implementation 'com.applandeo:material-calendar-view:1.7.0'
8283

8384
// test libraries
85+
implementation 'androidx.appcompat:appcompat:1.1.0'
8486
testImplementation 'junit:junit:4.12'
8587
androidTestImplementation 'androidx.test:runner:1.2.0'
8688
androidTestImplementation 'androidx.test:rules:1.2.0'
8789
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
8890

8991
implementation project(path: ':unitrackerlibrary')
92+
implementation 'androidx.work:work-runtime:2.2.0'
9093
}

app/src/main/AndroidManifest.xml

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,4 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<!--
3-
~ Copyright (C) 2019 Domjos
4-
~ This file is part of UniTrackerMobile <https://github.com/domjos1994/UniTrackerMobile>.
5-
~
6-
~ UniTrackerMobile is free software: you can redistribute it and/or modify
7-
~ it under the terms of the GNU General Public License as published by
8-
~ the Free Software Foundation, either version 3 of the License, or
9-
~ (at your option) any later version.
10-
~
11-
~ UniTrackerMobile is distributed in the hope that it will be useful,
12-
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
13-
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14-
~ GNU General Public License for more details.
15-
~
16-
~ You should have received a copy of the GNU General Public License
17-
~ along with UniTrackerMobile. If not, see <http://www.gnu.org/licenses/>.
18-
-->
19-
202
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
213
xmlns:dist="http://schemas.android.com/apk/distribution"
224
xmlns:tools="http://schemas.android.com/tools"
@@ -29,18 +11,22 @@
2911
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
3012

3113
<application
14+
android:name="androidx.multidex.MultiDexApplication"
3215
android:allowBackup="false"
3316
android:icon="@mipmap/ic_launcher"
3417
android:label="@string/app_name"
3518
android:roundIcon="@mipmap/ic_launcher_round"
3619
android:theme="@style/AppTheme"
3720
android:usesCleartextTraffic="true"
38-
android:name="androidx.multidex.MultiDexApplication"
3921
tools:targetApi="m">
40-
41-
<meta-data
42-
android:name="com.google.android.gms.ads.APPLICATION_ID"
43-
android:value="ca-app-pub-4983888966373182~7705161676" />
22+
<activity
23+
android:name=".activities.CalendarActivity"
24+
android:label="@string/calendar"
25+
android:parentActivityName=".activities.MainActivity">
26+
<meta-data
27+
android:name="android.support.PARENT_ACTIVITY"
28+
android:value="de.domjos.unitrackermobile.activities.MainActivity" />
29+
</activity>
4430

4531
<activity
4632
android:name=".activities.StatisticsActivity"

app/src/main/java/de/domjos/unitrackermobile/activities/AccountActivity.java

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@
3939
import com.google.android.material.bottomnavigation.BottomNavigationView;
4040

4141
import java.util.Arrays;
42-
import java.util.LinkedList;
4342
import java.util.List;
4443

4544
import de.domjos.unitrackerlibrary.interfaces.IBugService;
4645
import de.domjos.unitrackerlibrary.model.ListObject;
46+
import de.domjos.unitrackerlibrary.services.authentication.GithubTokenProvider;
4747
import de.domjos.unitrackerlibrary.services.engine.Authentication;
4848
import de.domjos.unitrackerlibrary.utils.Converter;
4949
import de.domjos.unitrackerlibrary.utils.MessageHelper;
@@ -57,8 +57,9 @@
5757

5858
public final class AccountActivity extends AbstractActivity {
5959
private SwipeRefreshDeleteList lvAccounts;
60-
private Spinner cmbAccountTracker;
60+
private Spinner cmbAccountTracker, cmbAccountAuthentication;
6161
private ArrayAdapter<Authentication.Tracker> trackerAdapter;
62+
private ArrayAdapter<Authentication.Auth> authAdapter;
6263
private EditText txtAccountServer, txtAccountUserName, txtAccountPassword,
6364
txtAccountAPI, txtAccountImageURL, txtAccountDescription, txtAccountExtended;
6465
private AutoCompleteTextView txtAccountTitle;
@@ -112,6 +113,7 @@ public void onItemSelected(AdapterView<?> parent, View view, int position, long
112113

113114
Authentication.Tracker item = trackerAdapter.getItem(position);
114115
if (item != null) {
116+
fillAuthByTracker(item);
115117
switch (item) {
116118
case Local:
117119
txtAccountServer.setText(Authentication.Tracker.Local.name());
@@ -270,6 +272,12 @@ protected void initControls() {
270272

271273
new Thread(() -> {
272274
try {
275+
if(!chkAccountGuest.isChecked()) {
276+
if(currentAccount.getAuthentication() == Authentication.Auth.OAUTH) {
277+
GithubTokenProvider githubTokenProvider = new GithubTokenProvider(currentAccount);
278+
currentAccount.setAPIKey(githubTokenProvider.refreshToken());
279+
}
280+
}
273281
IBugService bugService = Helper.getCurrentBugService(this.currentAccount, this.getApplicationContext());
274282
if (chkAccountGuest.isChecked() || bugService.testConnection()) {
275283
AccountActivity.this.runOnUiThread(() -> {
@@ -306,19 +314,17 @@ protected void initControls() {
306314
});
307315

308316
this.lvAccounts = this.findViewById(R.id.lvAccounts);
309-
this.cmbAccountTracker = this.findViewById(R.id.cmbAccountTracker);
310317

311-
// disable github
312-
List<Authentication.Tracker> trackers = new LinkedList<>();
313-
for(Authentication.Tracker tracker : Authentication.Tracker.values()) {
314-
if(tracker!= Authentication.Tracker.Github) {
315-
trackers.add(tracker);
316-
}
317-
}
318-
this.trackerAdapter = new ArrayAdapter<>(this.getApplicationContext(), R.layout.spinner_item, trackers);
318+
this.cmbAccountTracker = this.findViewById(R.id.cmbAccountTracker);
319+
this.trackerAdapter = new ArrayAdapter<>(this.getApplicationContext(), R.layout.spinner_item, Authentication.Tracker.values());
319320
this.cmbAccountTracker.setAdapter(this.trackerAdapter);
320321
this.trackerAdapter.notifyDataSetChanged();
321322

323+
this.cmbAccountAuthentication = this.findViewById(R.id.cmbAccountAuthentication);
324+
this.authAdapter = new ArrayAdapter<>(this.getApplicationContext(), R.layout.spinner_item);
325+
this.cmbAccountAuthentication.setAdapter(this.authAdapter);
326+
this.authAdapter.notifyDataSetChanged();
327+
322328
this.chkAccountGuest = this.findViewById(R.id.chkAccountGuest);
323329
this.txtAccountTitle = this.findViewById(R.id.txtAccountTitle);
324330
List<Authentication.Tracker> ls = Arrays.asList(Authentication.Tracker.values());
@@ -337,6 +343,25 @@ protected void initControls() {
337343
OnBoardingHelper.tutorialStep2(AccountActivity.this, () -> this.manageControls(true, true, false), this.findViewById(R.id.tblControls));
338344
}
339345

346+
private void fillAuthByTracker(Authentication.Tracker tracker) {
347+
this.authAdapter.clear();
348+
this.authAdapter.addAll(Authentication.Auth.values());
349+
switch (tracker) {
350+
case MantisBT:
351+
this.authAdapter.remove(Authentication.Auth.OAUTH);
352+
this.authAdapter.remove(Authentication.Auth.API_KEY);
353+
break;
354+
case YouTrack:
355+
this.authAdapter.remove(Authentication.Auth.OAUTH);
356+
this.authAdapter.remove(Authentication.Auth.Basic);
357+
break;
358+
case Github:
359+
this.authAdapter.remove(Authentication.Auth.Basic);
360+
this.authAdapter.remove(Authentication.Auth.API_KEY);
361+
break;
362+
}
363+
}
364+
340365
@Override
341366
protected void initValidators() {
342367
this.accountValidator = new Validator(this.getApplicationContext());
@@ -377,6 +402,7 @@ protected void manageControls(boolean editMode, boolean reset, boolean selected)
377402
this.txtAccountDescription.setEnabled(editMode);
378403
this.cmdAccountImageGallery.setEnabled(editMode);
379404
this.cmbAccountTracker.setEnabled(editMode);
405+
this.cmbAccountAuthentication.setEnabled(editMode);
380406
this.chkAccountGuest.setEnabled(editMode);
381407
this.txtAccountExtended.setEnabled(editMode);
382408

@@ -403,6 +429,11 @@ private void objectToControls() {
403429
this.cmbAccountTracker.setSelection(this.trackerAdapter.getPosition(Authentication.Tracker.Local));
404430
this.txtAccountServer.setText(Authentication.Tracker.Local.name());
405431
}
432+
if (this.currentAccount.getAuthentication() !=null) {
433+
this.cmbAccountAuthentication.setSelection(this.authAdapter.getPosition(this.currentAccount.getAuthentication()));
434+
} else {
435+
this.cmbAccountAuthentication.setSelection(this.authAdapter.getPosition(Authentication.Auth.Basic));
436+
}
406437
if (this.currentAccount.getCover() != null) {
407438
Bitmap bitmap = BitmapFactory.decodeByteArray(this.currentAccount.getCover(), 0, this.currentAccount.getCover().length);
408439
this.cmdAccountImageGallery.setImageBitmap(bitmap);
@@ -426,6 +457,7 @@ private void controlsToObject() {
426457
this.currentAccount.setDescription(this.txtAccountDescription.getText().toString());
427458
this.currentAccount.setTracker(this.trackerAdapter.getItem(this.cmbAccountTracker.getSelectedItemPosition()));
428459
this.currentAccount.setGuest(this.chkAccountGuest.isChecked());
460+
this.currentAccount.setAuthentication(this.authAdapter.getItem(this.cmbAccountAuthentication.getSelectedItemPosition()));
429461
if (this.cmdAccountImageGallery.getDrawable() instanceof BitmapDrawable) {
430462
this.currentAccount.setCover(Converter.convertDrawableToByteArray(this.cmdAccountImageGallery.getDrawable()));
431463
} else {
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
package de.domjos.unitrackermobile.activities;
2+
3+
import android.content.Intent;
4+
import android.graphics.Typeface;
5+
import android.graphics.drawable.Drawable;
6+
import android.os.Build;
7+
import android.view.View;
8+
import android.widget.LinearLayout;
9+
import android.widget.ProgressBar;
10+
import android.widget.TextView;
11+
12+
import com.applandeo.materialcalendarview.CalendarUtils;
13+
import com.applandeo.materialcalendarview.CalendarView;
14+
import com.applandeo.materialcalendarview.EventDay;
15+
16+
import java.util.Calendar;
17+
import java.util.Date;
18+
import java.util.LinkedList;
19+
import java.util.List;
20+
21+
import de.domjos.unitrackerlibrary.interfaces.IBugService;
22+
import de.domjos.unitrackerlibrary.model.issues.Issue;
23+
import de.domjos.unitrackerlibrary.model.objects.DescriptionObject;
24+
import de.domjos.unitrackerlibrary.model.projects.Project;
25+
import de.domjos.unitrackerlibrary.model.projects.Version;
26+
import de.domjos.unitrackerlibrary.services.engine.Authentication;
27+
import de.domjos.unitrackerlibrary.tasks.AbstractTask;
28+
import de.domjos.unitrackerlibrary.tasks.IssueTask;
29+
import de.domjos.unitrackerlibrary.tasks.ProjectTask;
30+
import de.domjos.unitrackerlibrary.tasks.VersionTask;
31+
import de.domjos.unitrackerlibrary.utils.MessageHelper;
32+
import de.domjos.unitrackermobile.R;
33+
import de.domjos.unitrackermobile.custom.AbstractActivity;
34+
import de.domjos.unitrackermobile.custom.CustomEventDay;
35+
import de.domjos.unitrackermobile.helper.Helper;
36+
37+
public class CalendarActivity extends AbstractActivity {
38+
private CalendarView calendarView;
39+
private ProgressBar progressBar;
40+
private LinearLayout llToObject;
41+
private TextView lblCalendarTitle, lblCalendarSubTitle;
42+
private List<EventDay> eventDays;
43+
private Intent intent;
44+
45+
46+
public CalendarActivity() {
47+
super(R.layout.calendar_activity);
48+
}
49+
50+
@Override
51+
protected void initActions() {
52+
this.calendarView.setOnDayClickListener(eventDay -> {
53+
if(eventDay instanceof CustomEventDay) {
54+
CustomEventDay customEventDay = (CustomEventDay) eventDay;
55+
56+
this.lblCalendarSubTitle.setText(customEventDay.getDescriptionObject().getTitle());
57+
if(customEventDay.getDescriptionObject() instanceof Project) {
58+
this.lblCalendarTitle.setText(this.getString(R.string.projects));
59+
this.intent = new Intent(this.getApplicationContext(), ProjectActivity.class);
60+
} else if(customEventDay.getDescriptionObject() instanceof Version) {
61+
this.lblCalendarTitle.setText(this.getString(R.string.versions));
62+
this.intent = new Intent(this.getApplicationContext(), VersionActivity.class);
63+
} else if(customEventDay.getDescriptionObject() instanceof Issue) {
64+
this.lblCalendarTitle.setText(this.getString(R.string.issues));
65+
this.intent = new Intent(this.getApplicationContext(), MainActivity.class);
66+
} else {
67+
this.lblCalendarTitle.setText(this.getString(R.string.calendar));
68+
this.intent = null;
69+
}
70+
71+
}
72+
});
73+
74+
this.llToObject.setOnClickListener(view -> {
75+
if(intent!=null) {
76+
startActivity(intent);
77+
}
78+
});
79+
}
80+
81+
@Override
82+
protected void initControls() {
83+
this.calendarView = this.findViewById(R.id.cvEventCalendar);
84+
this.progressBar = this.findViewById(R.id.pbCalendar);
85+
86+
this.llToObject = this.findViewById(R.id.llToObject);
87+
this.lblCalendarTitle = this.findViewById(R.id.lblCalendarTitle);
88+
this.lblCalendarSubTitle = this.findViewById(R.id.lblCalendarSubTitle);
89+
}
90+
91+
@Override
92+
protected void reload() {
93+
this.insertEvents();
94+
}
95+
96+
private void insertEvents() {
97+
try {
98+
this.progressBar.setVisibility(View.VISIBLE);
99+
List<Authentication> accounts = MainActivity.GLOBALS.getSqLiteGeneral().getAccounts("");
100+
this.eventDays = new LinkedList<>();
101+
for(Authentication account : accounts) {
102+
IBugService bugService = Helper.getCurrentBugService(account, this.getApplicationContext());
103+
104+
ProjectTask projectTask = new ProjectTask(CalendarActivity.this, bugService, false, false, R.drawable.ic_apps_black_24dp);
105+
projectTask.after(new AbstractTask.PostExecuteListener() {
106+
@Override
107+
public void onPostExecute(Object o) {
108+
if(o instanceof List) {
109+
List objects = (List) o;
110+
for (Object obj : objects) {
111+
if(obj instanceof Project) {
112+
Project project = (Project) obj;
113+
addEvent(project.getReleasedAt(), project.getTitle(), project);
114+
115+
VersionTask versionTask = new VersionTask(CalendarActivity.this, bugService, project.getId(), false, false, "versions", R.drawable.ic_update_black_24dp);
116+
versionTask.after(new AbstractTask.PostExecuteListener() {
117+
@Override
118+
public void onPostExecute(Object o) {
119+
List objList = (List) o;
120+
for(Object obj : objList) {
121+
Version version = (Version) obj;
122+
addEvent(version.getReleasedVersionAt(), String.format("%s: %s", project.getTitle(), version.getTitle()), version);
123+
}
124+
}
125+
});
126+
versionTask.execute(0);
127+
128+
IssueTask issueTask = new IssueTask(CalendarActivity.this, bugService, project.getId(), false, false, false, R.drawable.ic_bug_report_black_24dp);
129+
issueTask.after(new AbstractTask.PostExecuteListener() {
130+
@Override
131+
public void onPostExecute(Object o) {
132+
List objList = (List) o;
133+
loadingFinish(0, objList.size());
134+
int i = 0;
135+
for(Object obj : objList) {
136+
Issue issue = (Issue) obj;
137+
138+
IssueTask detailTasks = new IssueTask(CalendarActivity.this, bugService, project.getId(), false, true, false, R.drawable.ic_bug_report_black_24dp);
139+
detailTasks.after(new AbstractTask.PostExecuteListener() {
140+
@Override
141+
public void onPostExecute(Object o) {
142+
List obj = (List) o;
143+
Issue detailIssue = (Issue) obj.get(0);
144+
if(detailIssue.getDueDate() != null) {
145+
addEvent(detailIssue.getDueDate().getTime(), String.format("%s: %s", project.getTitle(), detailIssue.getTitle()), detailIssue);
146+
}
147+
}
148+
});
149+
detailTasks.execute(issue.getId());
150+
i++;
151+
loadingFinish(i, objList.size());
152+
}
153+
}
154+
});
155+
issueTask.execute(0);
156+
}
157+
}
158+
}
159+
}
160+
});
161+
projectTask.execute(0);
162+
}
163+
} catch (Exception ex) {
164+
MessageHelper.printException(ex, CalendarActivity.this);
165+
}
166+
}
167+
168+
private void loadingFinish(int current, int max) {
169+
this.progressBar.setMax(max);
170+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
171+
this.progressBar.setProgress(current, true);
172+
} else {
173+
this.progressBar.setProgress(current);
174+
}
175+
if(current==max) {
176+
this.progressBar.setVisibility(View.GONE);
177+
} else {
178+
this.progressBar.setVisibility(View.VISIBLE);
179+
}
180+
this.progressBar.invalidate();
181+
}
182+
183+
184+
private void addEvent(long time, String title, DescriptionObject descriptionObject) {
185+
Calendar calendar = Calendar.getInstance();
186+
Date dt = new Date();
187+
dt.setTime(time);
188+
calendar.setTime(dt);
189+
190+
Drawable drawable = CalendarUtils.getDrawableText(this.getApplicationContext(), title, Typeface.DEFAULT_BOLD, R.color.colorPrimary, 14);
191+
CustomEventDay customEventDay = new CustomEventDay(calendar, drawable, R.color.colorPrimary);
192+
customEventDay.setDescriptionObject(descriptionObject);
193+
this.eventDays.add(customEventDay);
194+
this.calendarView.setEvents(this.eventDays);
195+
this.calendarView.invalidate();
196+
}
197+
}

0 commit comments

Comments
 (0)