diff --git a/.github/workflows/make-ios-build.yaml b/.github/workflows/make-ios-build.yaml index 8005cdde8..92d30404b 100644 --- a/.github/workflows/make-ios-build.yaml +++ b/.github/workflows/make-ios-build.yaml @@ -14,15 +14,15 @@ env: BUILD_NUM_OFFSET: 246 # Final run number from previous repo before migration RUN_NUMBER: ${{ github.run_number }} PROJPATH: "visitz/Visitz" - DOTNET_SDK_VERSION: "8.0.402" - GLOBAL_JSON_PATH: "visitz/global.json" - XCODE_VERSION: "16.1.0" + DOTNET_SDK_VERSION: "9.0.305" + GLOBAL_JSON_PATH: "global.json" + XCODE_VERSION: "16.4" jobs: build-ios-package: name: Building, archiving and uploading IPA to GitHub - runs-on: macOS-14 + runs-on: macOS-15 environment: ${{ inputs.environment }} timeout-minutes: 200 steps: @@ -101,7 +101,7 @@ jobs: dotnet-version: ${{ env.DOTNET_SDK_VERSION }} - name: Cache .NET dependencies - uses: actions/cache@v4.2.2 + uses: actions/cache@v4.2.4 if: always() with: path: ~/.nuget/packages @@ -110,7 +110,7 @@ jobs: ${{ runner.os }}-nuget- - name: Cache .NET workloads - uses: actions/cache@v4.2.2 + uses: actions/cache@v4.2.4 if: always() with: path: ~/.dotnet @@ -120,12 +120,12 @@ jobs: - name: Install .NET MAUI ${{ env.MAUI_WORKLOAD_VERSION }} workloads run: | - dotnet workload install maui maui-ios + dotnet workload install maui maui-ios --version ${{ env.DOTNET_SDK_VERSION }} - name: .NET release build for iOS (${{ inputs.environment }}) run: | dotnet publish $PROJPATH \ - --framework net8.0-ios \ + --framework net9.0-ios \ --configuration Release \ -p:ApplicationVersion=${{ env.BUILD_NUM }} \ -p:DeploymentEnvironment=${{ vars.ENV_NAME }} \ @@ -144,11 +144,11 @@ jobs: - name: Prepare output package run: | - cd ${{ env.PROJPATH }}/bin/Release/net8.0-ios/ios-arm64/publish + cd ${{ env.PROJPATH }}/bin/Release/net9.0-ios/ios-arm64/publish mv "MCFD Mobility.ipa" "$OUTPUT_NAME.ipa" - name: Upload IPA archive (${{ inputs.environment }}) uses: actions/upload-artifact@v4.6.1 with: name: ${{ env.OUTPUT_NAME }} - path: ${{ env.PROJPATH }}/bin/Release/net8.0-ios/ios-arm64/publish/*.ipa + path: ${{ env.PROJPATH }}/bin/Release/net9.0-ios/ios-arm64/publish/*.ipa diff --git a/.github/workflows/unit-test-maui.yaml b/.github/workflows/unit-test-maui.yaml index 2c666986a..2b8c6051b 100644 --- a/.github/workflows/unit-test-maui.yaml +++ b/.github/workflows/unit-test-maui.yaml @@ -15,8 +15,8 @@ permissions: env: BASE_PROJPATH: "./visitz" - DOTNET_SDK_VERSION: "8.0.404" - GLOBAL_JSON_PATH: "visitz/global.json" + DOTNET_SDK_VERSION: "9.0.305" + GLOBAL_JSON_PATH: "global.json" jobs: run-maui-tests: @@ -50,7 +50,7 @@ jobs: dotnet nuget locals all --clear - name: Cache .NET dependencies - uses: actions/cache@v4.0.2 + uses: actions/cache@v5.0.2 if: always() with: path: ~/.nuget/packages @@ -59,7 +59,7 @@ jobs: ${{ runner.os }}-nuget- - name: Cache .NET workloads - uses: actions/cache@v4.0.2 + uses: actions/cache@v5.0.2 if: always() with: path: ~/.dotnet @@ -77,7 +77,7 @@ jobs: working-directory: ${{ env.BASE_PROJPATH }} run: | dotnet --version - dotnet build --framework net8.0 + dotnet build --framework net9.0 # Running with --no-build to work around an MSBuild targets issue. # (Details: build throws an error about a missing "Visitz.appSettings.json" file. That file should only exist @@ -87,7 +87,7 @@ jobs: run: | dotnet --version dotnet test ` - --framework net8.0 ` + --framework net9.0 ` --logger "trx;LogFilePrefix=${{ env.TEST_RESULTS }}" ` --no-build diff --git a/.gitignore b/.gitignore index 6c194c565..b623cd8fc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ # Mac File System .DS_Store + +# Dotnet config +global.json diff --git a/ONBOARDING.md b/ONBOARDING.md index 91550084e..149817f5e 100644 --- a/ONBOARDING.md +++ b/ONBOARDING.md @@ -41,7 +41,7 @@ Use this guide when setting up VSCode for the first time or updating framework v ### .NET -1. Install matching major version of .NET that matches the current MAUI requirements (MAUI 8 = .NET 8) +1. Install matching major version of .NET that matches the current MAUI requirements (MAUI 8 = .NET 8, MAUI 9 = .NET 9, etc.) - Make sure to install the latest minor/patch version @@ -63,17 +63,35 @@ Use this guide when setting up VSCode for the first time or updating framework v Install and set up extensions: -1. ### [C#](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp) +1. [C#](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp) -2. ### [C# Dev Kit](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit) +1. [C# Dev Kit](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit) Sign into C# Dev Kit extension with licensed account -1. ### [.NET MAUI](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-maui) +1. [.NET MAUI](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-maui) ***!!!*** There have been issues with other versions' debuggers, so if you have issues, try using version **1.3.29**. -4. ### [EditorConfig](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) +1. [EditorConfig](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) + +## Set up Apple certificates and provisioning profiles + +Assuming your Apple account is already authorized and can access certs and profiles for the project: + +1. Create a dummy project in XCode + +1. Give it the same bundle ID as the Visitz app (check [Visitz.csproj](visitz/Visitz/Visitz.csproj) for app ID) + +1. Enable "Automatically manage signing" and let XCode set up certs, CA's and provisioning profiles for you + +1. Try to build and run the dummy project, it will probably fail + +1. XCode should now have set up everything you need in the chain of trust to run development builds of the app + + ***!!!*** If your development certificate is still not trusted by the machine, you'll need to [manually download](https://www.apple.com/certificateauthority/AppleWWDRCAG3.cer) and install Apple's CA for dev certs + +--- # App launch setup diff --git a/build/Build-WindowsRelease.ps1 b/build/Build-WindowsRelease.ps1 index 7b28e77a3..ec125972c 100644 --- a/build/Build-WindowsRelease.ps1 +++ b/build/Build-WindowsRelease.ps1 @@ -69,7 +69,7 @@ function Ensure-Env { function Get-MsixFilePath { $filter = "Visitz*$BuildNumber*.msix" - $msix = Get-ChildItem . -Recurse -Filter $filter + $msix = (Get-ChildItem -Path .\artifacts\ -Recurse -Filter $filter)[0].FullName if (!(Test-Path $msix)) { Write-Error "No MSIX file matching filter '$filter' found in build directory (recursive search)" @@ -175,14 +175,14 @@ if ($SelfContained) { } if (!$SkipClean) { - dotnet clean "..\visitz\Visitz\Visitz.csproj" + dotnet clean "..\visitz\Visitz\Visitz.csproj" --framework net9.0-windows10.0.19041.0 rm $artifactsDir -Recurse -ErrorAction SilentlyContinue } dotnet publish "..\visitz\Visitz\Visitz.csproj" ` --artifacts-path ".\$artifactsDir" ` - --framework net8.0-windows10.0.19041.0 ` + --framework net9.0-windows10.0.19041.0 ` --configuration Release ` $selfContainedString ` -p:ApplicationVersion=$BuildNumber ` diff --git a/build/Sign-Msix.ps1 b/build/Sign-Msix.ps1 index 6763918ec..4c3f9ebcc 100644 --- a/build/Sign-Msix.ps1 +++ b/build/Sign-Msix.ps1 @@ -13,6 +13,7 @@ param( # https://learn.microsoft.com/en-us/windows/msix/package/sign-app-package-using-signtool#determine-the-hash-algorithm [string] $Algorithm = "", + # !!! Needs Windows SDK to be installed (possibly also "ClickOnce" publishing tools), check Visual Studio installer [string] $SignToolPath = "", [string] $CertificateThumbprint = "", @@ -36,6 +37,10 @@ if (-not $TimestampUrl) { if (-not $SignToolPath) { $paths = Get-ChildItem "C:\Program Files (x86)\Windows Kits\*\bin\*\x64" -Recurse -Filter "SignTool.exe" $SignToolPath = $paths[-1] + + if (-not $SignToolPath) { + throw "SignTool not found in Program Files. Make sure Windows SDK is installed (may also need to install ClickOnce). Check the Visual Studio Installer." + } } if (-not $Algorithm) { @@ -44,6 +49,10 @@ if (-not $Algorithm) { if (-not $CertificateThumbprint) { $CertificateThumbprint = Get-Env $CertificateThumbprintName -Scope $EnvScope + + if (-not $CertificateThumbprint) { + throw "No certificate thumbprint is set in environment variables." + } } Write-Host "Using SignTool from '$SignToolPath'" diff --git a/visitz/global.json.template b/global.json.template similarity index 100% rename from visitz/global.json.template rename to global.json.template diff --git a/visitz/.editorconfig b/visitz/.editorconfig index 6ec99eb40..fac5f5786 100644 --- a/visitz/.editorconfig +++ b/visitz/.editorconfig @@ -2,7 +2,6 @@ root = true [*] indent_style = tab -end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true diff --git a/visitz/.gitignore b/visitz/.gitignore index 72f33e2ce..2fa1b2843 100644 --- a/visitz/.gitignore +++ b/visitz/.gitignore @@ -374,7 +374,6 @@ local.properties # Directory Build overrides for local setups Directory.Build.Override.props -# MCFD Mobility +# visitz app appSettings.json MockIcmData/ -global.json.template diff --git a/visitz/Oidc/Oidc.csproj b/visitz/Oidc/Oidc.csproj index 3c3b2fd1a..d7855299b 100644 --- a/visitz/Oidc/Oidc.csproj +++ b/visitz/Oidc/Oidc.csproj @@ -1,8 +1,8 @@ - net8.0-ios;net8.0-maccatalyst;net8.0 - $(TargetFrameworks);net8.0-windows10.0.19041.0 + net9.0-ios;net9.0-maccatalyst;net9.0 + $(TargetFrameworks);net9.0-windows10.0.19041.0 true true @@ -29,7 +29,7 @@ runtime; build; native; contentfiles; analyzers - + diff --git a/visitz/Oidc/OidcSession.cs b/visitz/Oidc/OidcSession.cs index d444f5b45..989e57e4d 100644 --- a/visitz/Oidc/OidcSession.cs +++ b/visitz/Oidc/OidcSession.cs @@ -5,6 +5,9 @@ using Oidc.Exceptions; using Oidc.Network; using Oidc.Util; +using System.IdentityModel.Tokens.Jwt; + +#nullable enable namespace Oidc { @@ -13,10 +16,18 @@ public class OidcSession private static readonly string IdirActiveKey = "idir_active_employee"; private static readonly SemaphoreSlim Semaphore = new(1); + public static readonly double StaleThresholdMinutes = 7 * TimeSpan.MinutesPerDay; + private static AuthenticationClient AuthClient => ServicesProvider.Current.GetRequiredService(); - public static event EventHandler SessionChanged; + public static event EventHandler? SessionChanged; + + public static async Task IsSessionValid() + { + return await TokenHolder.IsAccessTokenValid() + || !await TokenHolder.IsRefreshTokenExpired(); + } static async Task DoAssertValidSessionAsync( string messageIfUnavailable, @@ -55,7 +66,7 @@ public static async Task AssertValidSessionAsync( public static async Task LoginAsync(string messageIfUnavailable, CancellationToken cancellationToken = default) { - LoginResult loginResult = null; + LoginResult? loginResult = null; try { @@ -63,7 +74,9 @@ public static async Task LoginAsync(string messageIfUnavailable, CancellationTok loginResult = await AuthClient.LoginAsync(cancellationToken); - if (loginResult.IsError) + if (loginResult == null) + throw new LoginException("No login result"); + else if (loginResult.IsError) { if (loginResult.Error == BrowserResultType.UserCancel.ToString()) // WORKAROUND String compare to BrowserResultType is a limitation of the library @@ -79,7 +92,7 @@ public static async Task LoginAsync(string messageIfUnavailable, CancellationTok bool success = !loginResult?.IsError ?? false; #if DEBUG ConsoleTrace.TraceMethod(typeof(OidcSession), - $"Login success: '{success}', Error: {loginResult.Error} -> '{loginResult.ErrorDescription}'"); + $"Login success: '{success}', Error: {loginResult?.Error} -> '{loginResult?.ErrorDescription}'"); #endif var info = await OidcSessionInfo.GetAsync(); SessionChanged?.Invoke(info, new LoginChangedEventArgs() { Success = success, }); @@ -88,7 +101,7 @@ public static async Task LoginAsync(string messageIfUnavailable, CancellationTok private static async Task RefreshAsync(string messageIfUnavailable) { - RefreshTokenResult refreshResult = null; + RefreshTokenResult? refreshResult = null; try { @@ -97,8 +110,8 @@ private static async Task RefreshAsync(string messageIfUnavailable) var refreshToken = await TokenHolder.GetRefreshTokenStringAsync(); refreshResult = await AuthClient.RefreshAsync(refreshToken); - if (refreshResult.IsError) - throw new SessionRefreshException(refreshResult.Error); + if (refreshResult == null || refreshResult.IsError) + throw new SessionRefreshException(refreshResult?.Error ?? "No refresh result"); await TokenHolder.SaveAsync(refreshResult); } @@ -173,7 +186,14 @@ public static async Task SessionExistsAsync() && await TokenHolder.GetIdentityTokenStringAsync() is not null; } - public static async Task IsAuthorized() + public static async Task IsSessionStale(double? minutesSinceExpiration = null) + { + JwtSecurityToken? access = await TokenHolder.GetAccessTokenAsync(); + TimeSpan? diff = DateTime.UtcNow - access?.ValidTo; + return diff?.TotalMinutes >= (minutesSinceExpiration ?? StaleThresholdMinutes); + } + + public static async Task IsAuthorizedAsync() { var status = await SecureStorage.Default.GetAsync(IdirActiveKey); return status != null ? bool.Parse(status) : null; @@ -181,10 +201,10 @@ public static async Task SessionExistsAsync() public static async Task SetAuthorization(bool? authorized) { - if (authorized == null) - SecureStorage.Default.Remove(IdirActiveKey); + if (authorized is bool auth) + await SecureStorage.Default.SetAsync(IdirActiveKey, auth.ToString()); else - await SecureStorage.Default.SetAsync(IdirActiveKey, authorized.ToString()); + SecureStorage.Default.Remove(IdirActiveKey); } } } diff --git a/visitz/OidcTest/OidcTest.csproj b/visitz/OidcTest/OidcTest.csproj index f2c7d243e..a5ba0b098 100644 --- a/visitz/OidcTest/OidcTest.csproj +++ b/visitz/OidcTest/OidcTest.csproj @@ -1,7 +1,7 @@ - net8.0 + net9.0 enable enable diff --git a/visitz/Visitz/Behaviors/Tags/ContactRelationshipTagBehavior.cs b/visitz/Visitz/Behaviors/Tags/ContactRelationshipTagBehavior.cs deleted file mode 100644 index 820ba9faf..000000000 --- a/visitz/Visitz/Behaviors/Tags/ContactRelationshipTagBehavior.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Visitz.Resources.Styles; -using Visitz.Views.TagViews; -using VisitzModel.Models.People; - -namespace Visitz.Behaviors.Tags; - -public class ContactRelationshipTagBehavior : TagStyleBehavior -{ - protected override void ApplyTagStyle(TagView tag) - { - if (tag.BindingContext is not IcmContact contact) - return; - - tag.Text = contact.Relationship; - - if (contact.IsKeyPlayer) - { - tag.BackgroundColor = VisitzColors.ContactRelationshipTagText; - tag.TextColor = Colors.White; - } - else - { - tag.BackgroundColor = VisitzColors.ContactRelationshipTagBackground; - tag.TextColor = VisitzColors.ContactRelationshipTagText; - } - } -} diff --git a/visitz/Visitz/Converters/TruthyStringToBoolConverter.cs b/visitz/Visitz/Converters/TruthyStringToBoolConverter.cs new file mode 100644 index 000000000..491d2a48c --- /dev/null +++ b/visitz/Visitz/Converters/TruthyStringToBoolConverter.cs @@ -0,0 +1,25 @@ +using System.Globalization; +using VisitzModel.Extensions; + +namespace Visitz.Converters; + +#nullable enable + +internal class TruthyStringToBoolConverter : IValueConverter +{ + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + if (value is string str) + return str.ParseWordTruthiness(); + else + return false; + } + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + if (value is bool b) + return b; + else + return false; + } +} diff --git a/visitz/Visitz/Platforms/Windows/Visitz/VisitzWindow.cs b/visitz/Visitz/Platforms/Windows/Visitz/VisitzWindow.cs index 17004ac71..9d5a1a2f6 100644 --- a/visitz/Visitz/Platforms/Windows/Visitz/VisitzWindow.cs +++ b/visitz/Visitz/Platforms/Windows/Visitz/VisitzWindow.cs @@ -1,3 +1,6 @@ +using CommunityToolkit.Mvvm.Messaging; +using Visitz.Services.Caseload; + namespace Visitz; public partial class VisitzWindow @@ -5,6 +8,8 @@ public partial class VisitzWindow private static readonly double InitialHeight = 800; private static readonly double WidthRatio = 1.5d; + bool AutoRefreshTriedOnce { get; set; } + private static partial Window ApplyDefaultWindowLayout(Window window) { window.Height = InitialHeight; @@ -12,4 +17,17 @@ private static partial Window ApplyDefaultWindowLayout(Window window) return window; } + + /// + /// Runs the AutoRefreshService after discarding the first attempt. This + /// is done as a workaround MAUI lifecycles—if we don't discard the first + /// run the app will crash. + /// + partial void TryRunAutoRefresh() + { + if (AutoRefreshTriedOnce) + WeakReferenceMessenger.Default.Send(AutoRefreshService.MakeStartMessage()); + else + AutoRefreshTriedOnce = true; + } } diff --git a/visitz/Visitz/Resources/Localization/LocalizedStrings.Designer.cs b/visitz/Visitz/Resources/Localization/LocalizedStrings.Designer.cs index 611270951..e0949ec34 100644 --- a/visitz/Visitz/Resources/Localization/LocalizedStrings.Designer.cs +++ b/visitz/Visitz/Resources/Localization/LocalizedStrings.Designer.cs @@ -19,7 +19,7 @@ namespace Visitz.Resources.Localization { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class LocalizedStrings { @@ -142,7 +142,7 @@ public static string Agt921 { } /// - /// Looks up a localized string similar to Coordination AGT (CA). + /// Looks up a localized string similar to Coord. AGT. /// public static string AgtCoordinationCa { get { @@ -240,6 +240,24 @@ public static string AuthorizationRequest { } } + /// + /// Looks up a localized string similar to MCFD Mobility wants to refresh your caseload. Log in to proceed.. + /// + public static string AutoCaseloadRefreshDesc { + get { + return ResourceManager.GetString("AutoCaseloadRefreshDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Attempted auto caseload refresh but it's disabled in debug options.. + /// + public static string AutoRefreshDebugDisabled { + get { + return ResourceManager.GetString("AutoRefreshDebugDisabled", resourceCulture); + } + } + /// /// Looks up a localized string similar to Birthdate. /// @@ -258,6 +276,15 @@ public static string Browse { } } + /// + /// Looks up a localized string similar to Use download button to refresh caseload. + /// + public static string ButtonToRefreshCaseload { + get { + return ResourceManager.GetString("ButtonToRefreshCaseload", resourceCulture); + } + } + /// /// Looks up a localized string similar to Cancel. /// @@ -276,6 +303,15 @@ public static string CancelAndKeepDraft { } } + /// + /// Looks up a localized string similar to Can't refresh caseload—internet connection unavailable. + /// + public static string CantRefreshNoInternet { + get { + return ResourceManager.GetString("CantRefreshNoInternet", resourceCulture); + } + } + /// /// Looks up a localized string similar to Caseload. /// @@ -323,6 +359,15 @@ public static string CaseloadIsEmpty { } } + /// + /// Looks up a localized string similar to Auto caseload refresh. + /// + public static string CaseloadRefresh { + get { + return ResourceManager.GetString("CaseloadRefresh", resourceCulture); + } + } + /// /// Looks up a localized string similar to Search by key player's name. /// @@ -332,6 +377,15 @@ public static string CaseloadSearchHint { } } + /// + /// Looks up a localized string similar to Cases. + /// + public static string Cases { + get { + return ResourceManager.GetString("Cases", resourceCulture); + } + } + /// /// Looks up a localized string similar to Case type. /// @@ -444,6 +498,15 @@ public static string CommentsClarificationPrompt { } } + /// + /// Looks up a localized string similar to Connect to the internet before trying again.. + /// + public static string ConnectBeforeRetry { + get { + return ResourceManager.GetString("ConnectBeforeRetry", resourceCulture); + } + } + /// /// Looks up a localized string similar to Connected—no internet available. /// @@ -534,6 +597,15 @@ public static string DateOfVisit { } } + /// + /// Looks up a localized string similar to Deceased. + /// + public static string Deceased { + get { + return ResourceManager.GetString("Deceased", resourceCulture); + } + } + /// /// Looks up a localized string similar to Description. /// @@ -1030,6 +1102,15 @@ public static string IncidentNumber { } } + /// + /// Looks up a localized string similar to Incidents. + /// + public static string Incidents { + get { + return ResourceManager.GetString("Incidents", resourceCulture); + } + } + /// /// Looks up a localized string similar to Indigenous. /// @@ -1821,6 +1902,24 @@ public static string RefreshingVisits { } } + /// + /// Looks up a localized string similar to Refresh interrupted. + /// + public static string RefreshInterrupted { + get { + return ResourceManager.GetString("RefreshInterrupted", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to MCFD Mobility was not able to refresh your caseload before your device lost its internet connection. It will automatically retry the next time your device is connected to internet.. + /// + public static string RefreshInterruptedDesc { + get { + return ResourceManager.GetString("RefreshInterruptedDesc", resourceCulture); + } + } + /// /// Looks up a localized string similar to Remove. /// @@ -2410,6 +2509,15 @@ public static string SocialWorkerName { } } + /// + /// Looks up a localized string similar to Caseload information on your device is out of date and needs to be refreshed before you can use the app.. + /// + public static string StaleSessionDesc { + get { + return ResourceManager.GetString("StaleSessionDesc", resourceCulture); + } + } + /// /// Looks up a localized string similar to Start survey. /// diff --git a/visitz/Visitz/Resources/Localization/LocalizedStrings.fr.resx b/visitz/Visitz/Resources/Localization/LocalizedStrings.fr.resx index a8aa01246..b952dfce3 100644 --- a/visitz/Visitz/Resources/Localization/LocalizedStrings.fr.resx +++ b/visitz/Visitz/Resources/Localization/LocalizedStrings.fr.resx @@ -1,68 +1,133 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Caseload - + Authentification requise - - + + + + + + + + \ No newline at end of file diff --git a/visitz/Visitz/Resources/Localization/LocalizedStrings.resx b/visitz/Visitz/Resources/Localization/LocalizedStrings.resx index 8c2aa1423..38c348ebb 100644 --- a/visitz/Visitz/Resources/Localization/LocalizedStrings.resx +++ b/visitz/Visitz/Resources/Localization/LocalizedStrings.resx @@ -953,7 +953,8 @@ No items here. 92.1 AGT - Coordination AGT (CA) + Coord. AGT + Coordination Agreement My caseload @@ -1008,4 +1009,40 @@ Do you want to download information for this record? Download record information + + Deceased + + + Cases + + + Incidents + + + Use download button to refresh caseload + + + Auto caseload refresh + + + MCFD Mobility wants to refresh your caseload. Log in to proceed. + + + Attempted auto caseload refresh but it's disabled in debug options. + + + Can't refresh caseload—internet connection unavailable + + + Refresh interrupted + + + MCFD Mobility was not able to refresh your caseload before your device lost its internet connection. It will automatically retry the next time your device is connected to internet. + + + Caseload information on your device is out of date and needs to be refreshed before you can use the app. + + + Connect to the internet before trying again. + \ No newline at end of file diff --git a/visitz/Visitz/Resources/Styles/Colors.xaml b/visitz/Visitz/Resources/Styles/Colors.xaml index d83c00d25..94929d921 100644 --- a/visitz/Visitz/Resources/Styles/Colors.xaml +++ b/visitz/Visitz/Resources/Styles/Colors.xaml @@ -140,4 +140,6 @@ #55000000 + #B30000 + diff --git a/visitz/Visitz/Resources/Styles/Dimensions.xaml b/visitz/Visitz/Resources/Styles/Dimensions.xaml index 3f74f9d3d..dcc0f2054 100644 --- a/visitz/Visitz/Resources/Styles/Dimensions.xaml +++ b/visitz/Visitz/Resources/Styles/Dimensions.xaml @@ -8,6 +8,8 @@ 10 20 - 10 - 10 + 5 + 10 + 10 + 20 diff --git a/visitz/Visitz/Resources/Styles/Styles.xaml b/visitz/Visitz/Resources/Styles/Styles.xaml index 7307d10c4..c7273c8a3 100644 --- a/visitz/Visitz/Resources/Styles/Styles.xaml +++ b/visitz/Visitz/Resources/Styles/Styles.xaml @@ -535,6 +535,10 @@ + +