Skip to content

Commit

Permalink
Merge pull request #1740 from instructure/release/parent-3.5.0-43
Browse files Browse the repository at this point in the history
Release Parent-3.5.0-43
  • Loading branch information
tamaskozmer authored Oct 7, 2022
2 parents 199c22a + e5c8fd4 commit 55c3ab0
Show file tree
Hide file tree
Showing 634 changed files with 11,813 additions and 5,397 deletions.
16 changes: 16 additions & 0 deletions PULL_REQUEST_TEMPLATE
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
--- edit or delete this section ---
## Screenshots

<table>
<tr><th>Before</th><th>After</th></tr>
<tr>
<td><img src="" maxHeight=500></td>
<td><img src="" maxHeight=500></td>
</tr>
</table>

## Checklist

- [ ] Follow-up e2e test ticket created or not needed
- [ ] A11y checked
- [ ] Approve from product or not needed
13 changes: 13 additions & 0 deletions apps/flutter_parent/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,19 @@ android {
shrinkResources false // Must be false, otherwise resources we need are erroneously stripped out
proguardFiles 'proguard-rules.pro'
}
applicationVariants.all{
variant ->
variant.outputs.each{
output->
project.ext { appName = 'parent' }
def dateTimeStamp = new Date().format('yyyy-MM-dd-HH-mm-ss')
def newName = output.outputFile.name
newName = newName.replace("app-", "$project.ext.appName-")
newName = newName.replace("-debug", "-dev-debug-" + dateTimeStamp)
newName = newName.replace("-release", "-prod-release")
output.outputFileName = newName
}
}
}
}

Expand Down
13 changes: 12 additions & 1 deletion apps/flutter_parent/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
android:windowSoftInputMode="adjustResize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
Expand Down Expand Up @@ -88,5 +89,15 @@
</intent-filter>
</receiver>

<provider
android:name="vn.hunghd.flutterdownloader.DownloadedFileProvider"
android:authorities="com.instructure.parentapp.flutter_downloader.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>

</application>
</manifest>
6 changes: 6 additions & 0 deletions apps/flutter_parent/lib/l10n/app_localizations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,12 @@ class AppLocalizations {
desc: 'Text for the find-my-school button',
);

String get findAnotherSchool => Intl.message(
'Find another school',
name: 'findAnotherSchool',
desc: 'Text for the find-another-school button',
);

/// Domain search screen
String get domainSearchInputHint => Intl.message(
Expand Down
9 changes: 8 additions & 1 deletion apps/flutter_parent/lib/l10n/res/intl_en.arb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"@@last_modified": "2022-01-28T12:37:40.360857",
"@@last_modified": "2022-10-06T10:11:41.858017",
"alertsLabel": "Alerts",
"@alertsLabel": {
"description": "The label for the Alerts tab",
Expand Down Expand Up @@ -259,6 +259,13 @@
"placeholders_order": [],
"placeholders": {}
},
"findAnotherSchool": "Find another school",
"@findAnotherSchool": {
"description": "Text for the find-another-school button",
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"domainSearchInputHint": "Enter school name or district…",
"@domainSearchInputHint": {
"description": "Input hint for the text box on the domain search screen",
Expand Down
2 changes: 1 addition & 1 deletion apps/flutter_parent/lib/l10n/res/intl_en_GB_instukhe.arb
Original file line number Diff line number Diff line change
Expand Up @@ -2660,4 +2660,4 @@
"placeholders_order": [],
"placeholders": {}
}
}
}
9 changes: 8 additions & 1 deletion apps/flutter_parent/lib/l10n/res/intl_messages.arb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"@@last_modified": "2022-01-28T12:37:40.360857",
"@@last_modified": "2022-10-06T10:11:41.858017",
"alertsLabel": "Alerts",
"@alertsLabel": {
"description": "The label for the Alerts tab",
Expand Down Expand Up @@ -259,6 +259,13 @@
"placeholders_order": [],
"placeholders": {}
},
"findAnotherSchool": "Find another school",
"@findAnotherSchool": {
"description": "Text for the find-another-school button",
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"domainSearchInputHint": "Enter school name or district…",
"@domainSearchInputHint": {
"description": "Input hint for the text box on the domain search screen",
Expand Down
11 changes: 11 additions & 0 deletions apps/flutter_parent/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

import 'dart:async';
import 'dart:io';
import 'dart:isolate';
import 'dart:ui';

import 'package:device_info/device_info.dart';
import 'package:firebase_core/firebase_core.dart';
Expand Down Expand Up @@ -49,6 +51,8 @@ void main() async {
]);
PandaRouter.init();

await FlutterDownloader.registerCallback(downloadCallback);

// This completer waits for the app to be built before allowing the notificationUtil to handle notifications
final Completer<void> _appCompleter = Completer<void>();
NotificationUtil.init(_appCompleter);
Expand All @@ -68,3 +72,10 @@ void main() async {
runApp(ParentApp(_appCompleter));
}, FirebaseCrashlytics.instance.recordError);
}

@pragma('vm:entry-point')
void downloadCallback(String id, DownloadTaskStatus status, int progress) {
final SendPort send =
IsolateNameServer.lookupPortByName('downloader_send_port');
send.send([id, status, progress]);
}
2 changes: 1 addition & 1 deletion apps/flutter_parent/lib/network/api/enrollments_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class EnrollmentsApi {
final dio = canvasDio(forceRefresh: forceRefresh);
final params = {
'state[]': ['active', 'completed'], // current_and_concluded state not supported for observers
//'user_id': studentId, <-- add this back when the api is fixed
'user_id': studentId,
if (gradingPeriodId?.isNotEmpty == true)
'grading_period_id': gradingPeriodId,
};
Expand Down
20 changes: 5 additions & 15 deletions apps/flutter_parent/lib/network/utils/analytics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import 'package:device_info/device_info.dart';
import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_parent/utils/debug_flags.dart';
Expand Down Expand Up @@ -79,28 +78,27 @@ class AnalyticsParamConstants {
}

class Analytics {
FirebaseAnalytics get _analytics => FirebaseAnalytics();

/// Set the current screen in Firebase Analytics
/// Set the current screen in analytics
void setCurrentScreen(String screenName) async {
if (kReleaseMode) {
await _analytics.setCurrentScreen(screenName: screenName);

}

if (DebugFlags.isDebug) {
print('currentScreen: $screenName');
}
}

/// Log an event to Firebase analytics (only in release mode).
/// Log an event to analytics (only in release mode).
/// If isDebug, it will also print to the console
///
/// Params
/// * [event] should be one of [AnalyticsEventConstants]
/// * [extras] a map of keys [AnalyticsParamConstants] to values. Use sparingly, we only get 25 unique parameters
void logEvent(String event, {Map<String, dynamic> extras = const {}}) async {
if (kReleaseMode) {
await _analytics.logEvent(name: event, parameters: extras);

}

if (DebugFlags.isDebug) {
Expand All @@ -122,14 +120,6 @@ class Analytics {

/// Sets environment properties such as the build type and SDK int. This only needs to be called once per session.
void setEnvironmentProperties() async {
var androidInfo = await DeviceInfoPlugin().androidInfo;
await _analytics.setUserProperty(
name: AnalyticsEventConstants.USER_PROPERTY_BUILD_TYPE,
value: kReleaseMode ? 'release' : 'debug',
);
await _analytics.setUserProperty(
name: AnalyticsEventConstants.USER_PROPERTY_OS_VERSION,
value: androidInfo.version.sdkInt.toString(),
);

}
}
25 changes: 25 additions & 0 deletions apps/flutter_parent/lib/network/utils/api_prefs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,19 @@ import 'dart:ui' as ui;
import 'package:encrypted_shared_preferences/encrypted_shared_preferences.dart';
import 'package:flutter/material.dart';
import 'package:flutter_parent/models/login.dart';
import 'package:flutter_parent/models/school_domain.dart';
import 'package:flutter_parent/models/serializers.dart';
import 'package:flutter_parent/models/user.dart';
import 'package:flutter_parent/network/api/auth_api.dart';
import 'package:flutter_parent/screens/web_login/web_login_screen.dart';
import 'package:flutter_parent/utils/db/calendar_filter_db.dart';
import 'package:flutter_parent/utils/db/reminder_db.dart';
import 'package:flutter_parent/utils/notification_util.dart';
import 'package:flutter_parent/utils/service_locator.dart';
import 'package:intl/intl.dart';
import 'package:package_info/package_info.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:tuple/tuple.dart';

import 'dio_config.dart';

Expand All @@ -42,6 +45,8 @@ class ApiPrefs {
static const String KEY_LOGINS = 'logins';
static const String KEY_RATING_DONT_SHOW_AGAIN = 'dont_show_again';
static const String KEY_RATING_NEXT_SHOW_DATE = 'next_show_date';
static const String KEY_LAST_ACCOUNT = 'last_account';
static const String KEY_LAST_ACCOUNT_LOGIN_FLOW = 'last_account_login_flow';

static EncryptedSharedPreferences _prefs;
static PackageInfo _packageInfo;
Expand Down Expand Up @@ -167,6 +172,26 @@ class ApiPrefs {
return _prefs.getStringList(KEY_LOGINS)?.map((it) => deserialize<Login>(json.decode(it)))?.toList() ?? [];
}

static setLastAccount(SchoolDomain lastAccount, LoginFlow loginFlow) {
_checkInit();
final lastAccountJson = json.encode(serialize(lastAccount));
_prefs.setString(KEY_LAST_ACCOUNT, lastAccountJson);
_prefs.setInt(KEY_LAST_ACCOUNT_LOGIN_FLOW, loginFlow.index);
}

static Tuple2<SchoolDomain, LoginFlow> getLastAccount() {
_checkInit();
if (!_prefs.containsKey(KEY_LAST_ACCOUNT)) return null;

final accountJson = _prefs.getString(KEY_LAST_ACCOUNT);
if (accountJson == null || accountJson.isEmpty) return null;

final lastAccount = deserialize<SchoolDomain>(json.decode(accountJson));
final loginFlow = _prefs.containsKey(KEY_LAST_ACCOUNT_LOGIN_FLOW) ? LoginFlow.values[_prefs.getInt(KEY_LAST_ACCOUNT_LOGIN_FLOW)] : LoginFlow.normal;

return Tuple2(lastAccount, loginFlow);
}

static Future<void> removeLogin(Login login) => removeLoginByUuid(login.uuid);

static Future<void> removeLoginByUuid(String uuid) async {
Expand Down
5 changes: 4 additions & 1 deletion apps/flutter_parent/lib/router/panda_router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,11 @@ class PandaRouter {

static String loginWeb(
String domain, {
String accountName = '',
String authenticationProvider = null,
LoginFlow loginFlow = LoginFlow.normal,
}) =>
'$_loginWeb?${_RouterKeys.domain}=${Uri.encodeQueryComponent(domain)}&${_RouterKeys.authenticationProvider}=$authenticationProvider&${_RouterKeys.loginFlow}=${loginFlow.toString()}';
'$_loginWeb?${_RouterKeys.domain}=${Uri.encodeQueryComponent(domain)}&${_RouterKeys.accountName}=${Uri.encodeQueryComponent(accountName)}&${_RouterKeys.authenticationProvider}=$authenticationProvider&${_RouterKeys.loginFlow}=${loginFlow.toString()}';

static String notParent() => '/not_parent';

Expand Down Expand Up @@ -325,6 +326,7 @@ class PandaRouter {

return WebLoginScreen(
params[_RouterKeys.domain][0],
accountName: params[_RouterKeys.accountName][0],
authenticationProvider: authProvider,
loginFlow: loginFlow,
);
Expand Down Expand Up @@ -507,6 +509,7 @@ class _RouterKeys {
static final calendarView = 'view_name';
static final courseId = 'courseId';
static final domain = 'domain';
static final accountName = 'accountName';
static final eventId = 'eventId';
static final infoText = 'infoText';
static final isCreatingAccount = 'isCreatingAccount';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,6 @@ class CourseDetailsModel extends BaseModel {
final enrollmentsFuture = _interactor()
.loadEnrollmentsForGradingPeriod(courseId, student.id, _nextGradingPeriod?.id, forceRefresh: forceRefresh)
?.then((enrollments) {
enrollments = enrollments
.where((element) => element.userId == student.id).toList();
return enrollments.length > 0 ? enrollments.first : null;
})?.catchError((_) => null); // Some 'legacy' parents can't read grades for students, so catch and return null

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,10 @@ class _AssignmentRow extends StatelessWidget {
final localizations = L10n(context);

final submission = assignment.submission(studentId);
if (submission?.grade != null) {
if (submission?.excused ?? false) {
text = localizations.gradeFormatScoreOutOfPointsPossible(localizations.excused, points);
semantics = localizations.contentDescriptionScoreOutOfPointsPossible('', points);
} else if (submission?.grade != null) {
text = localizations.gradeFormatScoreOutOfPointsPossible(submission.grade, points);
semantics = localizations.contentDescriptionScoreOutOfPointsPossible(submission.grade, points);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,11 @@ class _DomainSearchScreenState extends State<DomainSearchScreen> {
var item = _schoolDomains[index];
return ListTile(
title: Text(item.name),
onTap: () => locator<QuickNav>().pushRoute(context,
PandaRouter.loginWeb(item.domain, authenticationProvider: item.authenticationProvider)),
onTap: () {
final accountName = (item.name == null || item.name.isEmpty) ? item.domain : item.name;
return locator<QuickNav>().pushRoute(context,
PandaRouter.loginWeb(item.domain, accountName: accountName, authenticationProvider: item.authenticationProvider));
},
);
},
),
Expand Down Expand Up @@ -280,6 +283,6 @@ class _DomainSearchScreenState extends State<DomainSearchScreen> {
if (regExp.hasMatch(domain)) domain = regExp.stringMatch(domain);
if (domain.startsWith('www.')) domain = domain.substring(4); // Strip off www. if they typed it
if (!domain.contains('.') || domain.endsWith('.beta')) domain += '.instructure.com';
locator<QuickNav>().pushRoute(context, PandaRouter.loginWeb(domain, loginFlow: widget.loginFlow));
locator<QuickNav>().pushRoute(context, PandaRouter.loginWeb(domain, accountName: domain, loginFlow: widget.loginFlow));
}
}
Loading

0 comments on commit 55c3ab0

Please sign in to comment.