├── Dialer
├── Assets
│ ├── FullMDL2Assets.ttf
│ ├── NoContactIcon.png
│ ├── StoreLogo.backup.png
│ ├── BadgeLogo.scale-100.png
│ ├── BadgeLogo.scale-125.png
│ ├── BadgeLogo.scale-150.png
│ ├── BadgeLogo.scale-200.png
│ ├── BadgeLogo.scale-400.png
│ ├── LargeTile.scale-100.png
│ ├── LargeTile.scale-125.png
│ ├── LargeTile.scale-150.png
│ ├── LargeTile.scale-200.png
│ ├── LargeTile.scale-400.png
│ ├── SmallTile.scale-100.png
│ ├── SmallTile.scale-125.png
│ ├── SmallTile.scale-150.png
│ ├── SmallTile.scale-200.png
│ ├── SmallTile.scale-400.png
│ ├── StoreLogo.scale-100.png
│ ├── StoreLogo.scale-125.png
│ ├── StoreLogo.scale-150.png
│ ├── StoreLogo.scale-200.png
│ ├── StoreLogo.scale-400.png
│ ├── SplashScreen.scale-100.png
│ ├── SplashScreen.scale-125.png
│ ├── SplashScreen.scale-150.png
│ ├── SplashScreen.scale-200.png
│ ├── SplashScreen.scale-400.png
│ ├── LockScreenLogo.scale-200.png
│ ├── Square44x44Logo.scale-100.png
│ ├── Square44x44Logo.scale-125.png
│ ├── Square44x44Logo.scale-150.png
│ ├── Square44x44Logo.scale-200.png
│ ├── Square44x44Logo.scale-400.png
│ ├── Wide310x150Logo.scale-100.png
│ ├── Wide310x150Logo.scale-125.png
│ ├── Wide310x150Logo.scale-150.png
│ ├── Wide310x150Logo.scale-200.png
│ ├── Wide310x150Logo.scale-400.png
│ ├── Square150x150Logo.scale-100.png
│ ├── Square150x150Logo.scale-125.png
│ ├── Square150x150Logo.scale-150.png
│ ├── Square150x150Logo.scale-200.png
│ ├── Square150x150Logo.scale-400.png
│ ├── Square44x44Logo.targetsize-16.png
│ ├── Square44x44Logo.targetsize-24.png
│ ├── Square44x44Logo.targetsize-256.png
│ ├── Square44x44Logo.targetsize-32.png
│ ├── Square44x44Logo.targetsize-48.png
│ ├── Square44x44Logo.altform-unplated_targetsize-16.png
│ ├── Square44x44Logo.altform-unplated_targetsize-256.png
│ ├── Square44x44Logo.altform-unplated_targetsize-32.png
│ ├── Square44x44Logo.altform-unplated_targetsize-48.png
│ ├── Square44x44Logo.targetsize-24_altform-unplated.png
│ ├── Square44x44Logo.altform-lightunplated_targetsize-16.png
│ ├── Square44x44Logo.altform-lightunplated_targetsize-24.png
│ ├── Square44x44Logo.altform-lightunplated_targetsize-256.png
│ ├── Square44x44Logo.altform-lightunplated_targetsize-32.png
│ └── Square44x44Logo.altform-lightunplated_targetsize-48.png
├── Systems
│ ├── MessagingSystem.cs
│ ├── DeviceSystem.cs
│ ├── ContactSystem.cs
│ ├── PermissionSystem.cs
│ └── BackgroundSystem.cs
├── Properties
│ ├── launchSettings.json
│ └── PublishProfiles
│ │ ├── win10-x64.pubxml
│ │ ├── win10-x86.pubxml
│ │ └── win10-arm64.pubxml
├── UI
│ ├── Pages
│ │ ├── PhoneLinesSettings.xaml
│ │ ├── NotificationsSettings.xaml
│ │ ├── PhoneLineSettings.xaml.cs
│ │ ├── PhoneLinesSettings.xaml.cs
│ │ ├── NotificationsSettings.xaml.cs
│ │ ├── PersonalizationSettings.xaml.cs
│ │ ├── AboutSettings.xaml.cs
│ │ ├── SettingsPage.xaml.cs
│ │ ├── ApplicationsSettings.xaml.cs
│ │ ├── HistoryPage.xaml.cs
│ │ ├── HistoryPage.xaml
│ │ ├── PhoneLineSettings.xaml
│ │ ├── SettingsPage.xaml
│ │ ├── PersonalizationSettings.xaml
│ │ ├── MainPage.xaml
│ │ ├── ContactsPage.xaml
│ │ ├── ApplicationsSettings.xaml
│ │ ├── ContactsPage.xaml.cs
│ │ ├── MainPage.xaml.cs
│ │ ├── DialPage.xaml
│ │ ├── AboutSettings.xaml
│ │ ├── CallUIPage.xaml.cs
│ │ └── DialPage.xaml.cs
│ ├── Converters
│ │ ├── PageNameToTextString.cs
│ │ ├── CallToCallLengthTextString.cs
│ │ ├── CallHistoryEntryToContact.cs
│ │ ├── CallHistoryEntryToCallStateGlyphString.cs
│ │ ├── PhoneLineToDisplayNameText.cs
│ │ ├── Converters.xaml
│ │ ├── CallHistoryEntryToCallStateTextString.cs
│ │ ├── DateTimeToString.cs
│ │ ├── PageNameToGlyphString.cs
│ │ ├── CallToCallStateGlyphString.cs
│ │ ├── CallHistoryEntryToLineDisplayNameText.cs
│ │ ├── CallToCallStateTextString.cs
│ │ └── CallHistoryEntryToLineIconBitmap.cs
│ ├── Controls
│ │ ├── AdditionalPhoneContactPresenter.xaml.cs
│ │ ├── DigitButton.xaml.cs
│ │ ├── CallHistoryEntryPresenter.xaml.cs
│ │ ├── DigitButton.xaml
│ │ ├── LinePresenter.xaml.cs
│ │ ├── LinePresenter.xaml
│ │ ├── CallStatePresenter.xaml
│ │ ├── DialPad.xaml.cs
│ │ ├── CallStatePresenter.xaml.cs
│ │ ├── AdditionalPhoneContactPresenter.xaml
│ │ ├── SmallCallPresenter.xaml
│ │ ├── SmallCallPresenter.xaml.cs
│ │ ├── VerticalIndexScrollbar.xaml
│ │ ├── VerticalIndexScrollbar.xaml.cs
│ │ ├── DialPad.xaml
│ │ ├── ContactControl.xaml
│ │ ├── ContactControl.xaml.cs
│ │ ├── CallHistoryEntryPresenter.xaml
│ │ ├── TitlebarControl.xaml
│ │ └── TitlebarControl.xaml.cs
│ ├── ViewModel
│ │ ├── ViewModelCore.cs
│ │ └── AboutViewModel.cs
│ └── Glyphs.cs
├── Helpers
│ ├── DateTimeOffsetComparer.cs
│ ├── ReadOnlyObservableCollection2.cs
│ ├── ToastButtonEqualityComparer.cs
│ ├── RelayCommand.cs
│ └── SettingsManager.cs
├── BackgroungCallMonitor.cs
├── app.manifest
├── MainWindow.xaml
├── Dialer.csproj
├── Package.appxmanifest
├── App.xaml
├── MainWindow.xaml.cs
└── Strings
│ └── it-IT
│ └── Resources.resw
├── .gitignore
├── .gitmodules
├── LICENSE
├── README.md
└── Dialer.sln
/Dialer/Assets/FullMDL2Assets.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/FullMDL2Assets.ttf
--------------------------------------------------------------------------------
/Dialer/Assets/NoContactIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/NoContactIcon.png
--------------------------------------------------------------------------------
/Dialer/Assets/StoreLogo.backup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/StoreLogo.backup.png
--------------------------------------------------------------------------------
/Dialer/Assets/BadgeLogo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/BadgeLogo.scale-100.png
--------------------------------------------------------------------------------
/Dialer/Assets/BadgeLogo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/BadgeLogo.scale-125.png
--------------------------------------------------------------------------------
/Dialer/Assets/BadgeLogo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/BadgeLogo.scale-150.png
--------------------------------------------------------------------------------
/Dialer/Assets/BadgeLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/BadgeLogo.scale-200.png
--------------------------------------------------------------------------------
/Dialer/Assets/BadgeLogo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/BadgeLogo.scale-400.png
--------------------------------------------------------------------------------
/Dialer/Assets/LargeTile.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/LargeTile.scale-100.png
--------------------------------------------------------------------------------
/Dialer/Assets/LargeTile.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/LargeTile.scale-125.png
--------------------------------------------------------------------------------
/Dialer/Assets/LargeTile.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/LargeTile.scale-150.png
--------------------------------------------------------------------------------
/Dialer/Assets/LargeTile.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/LargeTile.scale-200.png
--------------------------------------------------------------------------------
/Dialer/Assets/LargeTile.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/LargeTile.scale-400.png
--------------------------------------------------------------------------------
/Dialer/Assets/SmallTile.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/SmallTile.scale-100.png
--------------------------------------------------------------------------------
/Dialer/Assets/SmallTile.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/SmallTile.scale-125.png
--------------------------------------------------------------------------------
/Dialer/Assets/SmallTile.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/SmallTile.scale-150.png
--------------------------------------------------------------------------------
/Dialer/Assets/SmallTile.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/SmallTile.scale-200.png
--------------------------------------------------------------------------------
/Dialer/Assets/SmallTile.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/SmallTile.scale-400.png
--------------------------------------------------------------------------------
/Dialer/Assets/StoreLogo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/StoreLogo.scale-100.png
--------------------------------------------------------------------------------
/Dialer/Assets/StoreLogo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/StoreLogo.scale-125.png
--------------------------------------------------------------------------------
/Dialer/Assets/StoreLogo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/StoreLogo.scale-150.png
--------------------------------------------------------------------------------
/Dialer/Assets/StoreLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/StoreLogo.scale-200.png
--------------------------------------------------------------------------------
/Dialer/Assets/StoreLogo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/StoreLogo.scale-400.png
--------------------------------------------------------------------------------
/Dialer/Assets/SplashScreen.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/SplashScreen.scale-100.png
--------------------------------------------------------------------------------
/Dialer/Assets/SplashScreen.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/SplashScreen.scale-125.png
--------------------------------------------------------------------------------
/Dialer/Assets/SplashScreen.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/SplashScreen.scale-150.png
--------------------------------------------------------------------------------
/Dialer/Assets/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/Dialer/Assets/SplashScreen.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/SplashScreen.scale-400.png
--------------------------------------------------------------------------------
/Dialer/Systems/MessagingSystem.cs:
--------------------------------------------------------------------------------
1 | namespace Dialer.Systems
2 | {
3 | public sealed class MessagingSystem
4 | {
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Dialer/Assets/LockScreenLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/LockScreenLogo.scale-200.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square44x44Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square44x44Logo.scale-100.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square44x44Logo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square44x44Logo.scale-125.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square44x44Logo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square44x44Logo.scale-150.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square44x44Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square44x44Logo.scale-400.png
--------------------------------------------------------------------------------
/Dialer/Assets/Wide310x150Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Wide310x150Logo.scale-100.png
--------------------------------------------------------------------------------
/Dialer/Assets/Wide310x150Logo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Wide310x150Logo.scale-125.png
--------------------------------------------------------------------------------
/Dialer/Assets/Wide310x150Logo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Wide310x150Logo.scale-150.png
--------------------------------------------------------------------------------
/Dialer/Assets/Wide310x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Wide310x150Logo.scale-200.png
--------------------------------------------------------------------------------
/Dialer/Assets/Wide310x150Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Wide310x150Logo.scale-400.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square150x150Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square150x150Logo.scale-100.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square150x150Logo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square150x150Logo.scale-125.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square150x150Logo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square150x150Logo.scale-150.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square150x150Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square150x150Logo.scale-400.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square44x44Logo.targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square44x44Logo.targetsize-16.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square44x44Logo.targetsize-24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square44x44Logo.targetsize-24.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square44x44Logo.targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square44x44Logo.targetsize-256.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square44x44Logo.targetsize-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square44x44Logo.targetsize-32.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square44x44Logo.targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square44x44Logo.targetsize-48.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vs
2 | packages
3 | releases
4 | PreparedInstaller
5 | Dialer/AppPackages
6 | Dialer/BundleArtifacts
7 | Dialer/*.user
8 | **/*.pfx
9 | */obj
10 | */bin
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "Internal.Windows.Calls"]
2 | path = Internal.Windows.Calls
3 | url = https://github.com/WOA-Project/Internal.Windows.Calls.git
4 | branch = wp/main
5 |
--------------------------------------------------------------------------------
/Dialer/Assets/Square44x44Logo.altform-unplated_targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square44x44Logo.altform-unplated_targetsize-16.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square44x44Logo.altform-unplated_targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square44x44Logo.altform-unplated_targetsize-256.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square44x44Logo.altform-unplated_targetsize-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square44x44Logo.altform-unplated_targetsize-32.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square44x44Logo.altform-unplated_targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square44x44Logo.altform-unplated_targetsize-48.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square44x44Logo.targetsize-24_altform-unplated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square44x44Logo.altform-lightunplated_targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square44x44Logo.altform-lightunplated_targetsize-16.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square44x44Logo.altform-lightunplated_targetsize-24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square44x44Logo.altform-lightunplated_targetsize-24.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square44x44Logo.altform-lightunplated_targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square44x44Logo.altform-lightunplated_targetsize-256.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square44x44Logo.altform-lightunplated_targetsize-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square44x44Logo.altform-lightunplated_targetsize-32.png
--------------------------------------------------------------------------------
/Dialer/Assets/Square44x44Logo.altform-lightunplated_targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WOA-Project/woadialer/HEAD/Dialer/Assets/Square44x44Logo.altform-lightunplated_targetsize-48.png
--------------------------------------------------------------------------------
/Dialer/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "Dialer (Package)": {
4 | "commandName": "MsixPackage",
5 | "nativeDebugging": true
6 | },
7 | "Dialer (Unpackaged)": {
8 | "commandName": "Project"
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/Dialer/UI/Pages/PhoneLinesSettings.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/NotificationsSettings.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Dialer/Helpers/DateTimeOffsetComparer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Dialer.Helpers
5 | {
6 | public sealed class DateTimeOffsetComparer : IComparer
7 | {
8 | public static DateTimeOffsetComparer Comparer { get; } = new DateTimeOffsetComparer();
9 |
10 | public int Compare(DateTimeOffset? x, DateTimeOffset? y)
11 | {
12 | return x == null && y == null ? 0 : x == null ? 1 : y == null ? -1 : DateTimeOffset.Compare(x.Value, y.Value);
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Dialer/BackgroungCallMonitor.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using Windows.ApplicationModel.Background;
3 |
4 | namespace Dialer
5 | {
6 | public sealed class BackgroungCallMonitor : IBackgroundTask
7 | {
8 | private BackgroundTaskDeferral _Deferral;
9 | private readonly ManualResetEvent a = new(false);
10 |
11 | public void Run(IBackgroundTaskInstance taskInstance)
12 | {
13 | _Deferral = taskInstance.GetDeferral();
14 | _ = a.WaitOne();
15 | _Deferral.Complete();
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/PhoneLineSettings.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.UI.Xaml.Controls;
2 |
3 | // Документацию по шаблону элемента "Пустая страница" см. по адресу https://go.microsoft.com/fwlink/?LinkId=234238
4 |
5 | namespace Dialer.UI.Pages
6 | {
7 | ///
8 | /// Пустая страница, которую можно использовать саму по себе или для перехода внутри фрейма.
9 | ///
10 | public sealed partial class PhoneLineSettings : Page
11 | {
12 | public PhoneLineSettings()
13 | {
14 | InitializeComponent();
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/PhoneLinesSettings.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.UI.Xaml.Controls;
2 |
3 | // Документацию по шаблону элемента "Пустая страница" см. по адресу https://go.microsoft.com/fwlink/?LinkId=234238
4 |
5 | namespace Dialer.UI.Pages
6 | {
7 | ///
8 | /// Пустая страница, которую можно использовать саму по себе или для перехода внутри фрейма.
9 | ///
10 | public sealed partial class PhoneLinesSettings : Page
11 | {
12 | public PhoneLinesSettings()
13 | {
14 | InitializeComponent();
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/NotificationsSettings.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.UI.Xaml.Controls;
2 |
3 | // Документацию по шаблону элемента "Пустая страница" см. по адресу https://go.microsoft.com/fwlink/?LinkId=234238
4 |
5 | namespace Dialer.UI.Pages
6 | {
7 | ///
8 | /// Пустая страница, которую можно использовать саму по себе или для перехода внутри фрейма.
9 | ///
10 | public sealed partial class NotificationsSettings : Page
11 | {
12 | public NotificationsSettings()
13 | {
14 | InitializeComponent();
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/PersonalizationSettings.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.UI.Xaml.Controls;
2 |
3 | // Документацию по шаблону элемента "Пустая страница" см. по адресу https://go.microsoft.com/fwlink/?LinkId=234238
4 |
5 | namespace Dialer.UI.Pages
6 | {
7 | ///
8 | /// Пустая страница, которую можно использовать саму по себе или для перехода внутри фрейма.
9 | ///
10 | public sealed partial class PersonalizationSettings : Page
11 | {
12 | public PersonalizationSettings()
13 | {
14 | InitializeComponent();
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Dialer/Helpers/ReadOnlyObservableCollection2.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.ObjectModel;
2 | using System.Collections.Specialized;
3 |
4 | namespace Dialer.Helpers
5 | {
6 | public sealed class ReadOnlyObservableCollection2 : ReadOnlyObservableCollection
7 | {
8 | public new event NotifyCollectionChangedEventHandler CollectionChanged
9 | {
10 | add => base.CollectionChanged += value;
11 | remove => base.CollectionChanged -= value;
12 | }
13 |
14 | public ReadOnlyObservableCollection2(ObservableCollection list) : base(list)
15 | {
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/AboutSettings.xaml.cs:
--------------------------------------------------------------------------------
1 | using Dialer.UI.ViewModel;
2 | using Microsoft.UI.Xaml;
3 | using Microsoft.UI.Xaml.Controls;
4 |
5 | namespace Dialer.UI.Pages
6 | {
7 | public sealed partial class AboutSettings : Page
8 | {
9 | public AboutViewModel ViewModel
10 | {
11 | get;
12 | }
13 |
14 | public AboutSettings()
15 | {
16 | RequestedTheme = (App.Window.Content as FrameworkElement)?.RequestedTheme ?? ElementTheme.Default;
17 | InitializeComponent();
18 | ViewModel = new AboutViewModel(DispatcherQueue);
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Dialer/UI/Converters/PageNameToTextString.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.UI.Xaml.Data;
2 | using System;
3 |
4 | namespace Dialer.UI.Converters
5 | {
6 | public sealed class PageNameToTextString : IValueConverter
7 | {
8 | public object Convert(object value, Type targetType, object parameter, string language)
9 | {
10 | return value is string name ? App.Current.ResourceLoader.GetString(name) : throw new ArgumentException();
11 | }
12 |
13 | public object ConvertBack(object value, Type targetType, object parameter, string language)
14 | {
15 | throw new NotImplementedException();
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Dialer/UI/Controls/AdditionalPhoneContactPresenter.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.UI.Xaml.Controls;
2 |
3 |
4 | namespace Dialer.UI.Controls
5 | {
6 | public sealed partial class AdditionalPhoneContactPresenter : UserControl
7 | {
8 | public string PhoneType
9 | {
10 | get => PhoneTypeTB.Text;
11 | set => PhoneTypeTB.Text = value;
12 | }
13 |
14 | public string PhoneNumber
15 | {
16 | get => PhoneNumberTB.Text;
17 | set => PhoneNumberTB.Text = value;
18 | }
19 |
20 | public AdditionalPhoneContactPresenter()
21 | {
22 | InitializeComponent();
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/SettingsPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using Dialer.Systems;
2 | using Microsoft.UI.Xaml.Controls;
3 |
4 | namespace Dialer.UI.Pages
5 | {
6 | public sealed partial class SettingsPage : Page
7 | {
8 | public UISystem UISystem => App.Current.UISystem;
9 |
10 | public SettingsPage()
11 | {
12 | InitializeComponent();
13 | }
14 |
15 | private void NavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
16 | {
17 | if (UISystem.PageNameToType(args.SelectedItem.ToString()) != null)
18 | {
19 | _ = ContentFrame.Navigate(UISystem.PageNameToType(args.SelectedItem.ToString()));
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Dialer/UI/Controls/DigitButton.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.UI.Xaml.Controls;
2 |
3 | namespace Dialer.UI.Controls
4 | {
5 | public sealed partial class DigitButton : Button
6 | {
7 | public string Chars
8 | {
9 | get => tb_Chars.Text;
10 | set => tb_Chars.Text = value;
11 | }
12 | public string AdditionalChars
13 | {
14 | get => tb_AdditionalChars.Text;
15 | set => tb_AdditionalChars.Text = value;
16 | }
17 | public string Digit
18 | {
19 | get => tb_Digit.Text;
20 | set => tb_Digit.Text = value;
21 | }
22 |
23 | public DigitButton()
24 | {
25 | InitializeComponent();
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Dialer/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 | true/PM
12 | PerMonitorV2, PerMonitor
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/ApplicationsSettings.xaml.cs:
--------------------------------------------------------------------------------
1 | using Dialer.Helpers;
2 | using Microsoft.UI.Xaml.Controls;
3 | using Microsoft.UI.Xaml.Navigation;
4 |
5 | namespace Dialer.UI.Pages
6 | {
7 | public sealed partial class ApplicationsSettings : Page
8 | {
9 | public ApplicationsSettings()
10 | {
11 | InitializeComponent();
12 | }
13 |
14 | protected override void OnNavigatedTo(NavigationEventArgs e)
15 | {
16 | base.OnNavigatedTo(e);
17 | ProximitySensorSettingToggle.IsOn = SettingsManager.getProximitySensorOn();
18 | }
19 |
20 | private void ProximitySensorSettingToggle_Toggled(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
21 | {
22 | SettingsManager.setProximitySensorOn(((ToggleSwitch)e.OriginalSource).IsOn);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Dialer/Helpers/ToastButtonEqualityComparer.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.WinUI.Notifications;
2 | using System.Collections.Generic;
3 |
4 | namespace Dialer.Helpers
5 | {
6 | public sealed class ToastButtonEqualityComparer : IEqualityComparer
7 | {
8 | public static ToastButtonEqualityComparer EqualityComparer { get; } = new ToastButtonEqualityComparer();
9 |
10 | private ToastButtonEqualityComparer()
11 | {
12 | }
13 |
14 | public bool Equals(ToastButton x, ToastButton y)
15 | {
16 | return (x == null && y == null) || (x != null && y != null && x.Arguments == y.Arguments && x.Content == y.Content);
17 | }
18 |
19 | public int GetHashCode(ToastButton obj)
20 | {
21 | return obj == null ? 0 : obj.Arguments.GetHashCode() ^ obj.Content.GetHashCode();
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Dialer/Properties/PublishProfiles/win10-x64.pubxml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | FileSystem
8 | x64
9 | win10-x64
10 | bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\
11 | true
12 | False
13 | False
14 | True
15 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Dialer/Properties/PublishProfiles/win10-x86.pubxml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | FileSystem
8 | x86
9 | win10-x86
10 | bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\
11 | true
12 | False
13 | False
14 | True
15 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Dialer/Properties/PublishProfiles/win10-arm64.pubxml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | FileSystem
8 | arm64
9 | win10-arm64
10 | bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\
11 | true
12 | False
13 | False
14 | True
15 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Dialer/UI/Controls/CallHistoryEntryPresenter.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.UI.Xaml;
2 | using Microsoft.UI.Xaml.Controls;
3 | using Windows.ApplicationModel.Calls;
4 |
5 | namespace Dialer.UI.Controls
6 | {
7 | public sealed partial class CallHistoryEntryPresenter : UserControl
8 | {
9 | public static readonly DependencyProperty PresentedEntryProperty = DependencyProperty.Register(nameof(PresentedEntry), typeof(PhoneCallHistoryEntry), typeof(CallHistoryEntryPresenter), new PropertyMetadata(null));
10 |
11 | public PhoneCallHistoryEntry PresentedEntry
12 | {
13 | get => (PhoneCallHistoryEntry)GetValue(PresentedEntryProperty);
14 | set => SetValue(PresentedEntryProperty, value);
15 | }
16 |
17 | public bool ContactPresented => !string.IsNullOrEmpty(PresentedEntry?.Address.ContactId);
18 |
19 | public CallHistoryEntryPresenter()
20 | {
21 | InitializeComponent();
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/HistoryPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using Dialer.Systems;
2 | using Microsoft.UI.Xaml.Controls;
3 | using Microsoft.UI.Xaml.Media.Animation;
4 | using Windows.ApplicationModel.Calls;
5 |
6 | namespace Dialer.UI.Pages
7 | {
8 | public sealed partial class HistoryPage : Page
9 | {
10 | private CallSystem CallSystem => App.Current.CallSystem;
11 |
12 | public HistoryPage()
13 | {
14 | InitializeComponent();
15 | }
16 |
17 | private void ListView_ItemClick(object sender, ItemClickEventArgs e)
18 | {
19 | if (e.ClickedItem is PhoneCallHistoryEntry entry)
20 | {
21 | switch (entry.Address.RawAddressKind)
22 | {
23 | case PhoneCallHistoryEntryRawAddressKind.PhoneNumber:
24 | ((App.Window.Content as Frame)?.Content as MainPage)?.Navigate(UISystem.DIAL_PAGE, new EntranceNavigationTransitionInfo(), entry.Address.RawAddress);
25 | break;
26 | }
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Dialer/UI/Converters/CallToCallLengthTextString.cs:
--------------------------------------------------------------------------------
1 | using Internal.Windows.Calls;
2 | using Microsoft.UI.Xaml.Data;
3 | using System;
4 |
5 | namespace Dialer.UI.Converters
6 | {
7 | public sealed class CallToCallLengthTextString : IValueConverter
8 | {
9 | public object Convert(object value, Type targetType, object parameter, string language)
10 | {
11 | switch (value)
12 | {
13 | case Call call:
14 | string length = (DateTimeOffset.Now - call.CallArrivalTime)?.TotalSeconds >= 1
15 | ? (DateTimeOffset.Now - call.CallArrivalTime)?.ToString("mm\\:ss") ?? string.Empty
16 | : (DateTimeOffset.Now - call.StartTime)?.ToString("mm\\:ss") ?? string.Empty;
17 | return length;
18 | default:
19 | return string.Empty;
20 | }
21 | }
22 |
23 | public object ConvertBack(object value, Type targetType, object parameter, string language)
24 | {
25 | throw new NotImplementedException();
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Dialer/UI/Controls/DigitButton.xaml:
--------------------------------------------------------------------------------
1 |
23 |
--------------------------------------------------------------------------------
/Dialer/UI/Converters/CallHistoryEntryToContact.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.UI.Xaml.Data;
2 | using System;
3 | using Windows.ApplicationModel.Calls;
4 |
5 | namespace Dialer.UI.Converters
6 | {
7 | public sealed class CallHistoryEntryToContact : IValueConverter
8 | {
9 | public object Convert(object value, Type targetType, object parameter, string language)
10 | {
11 | if (value is PhoneCallHistoryEntry entry && !string.IsNullOrEmpty(entry.Address.ContactId))
12 | {
13 | Windows.Foundation.IAsyncOperation task0 = App.Current.CallSystem.ContactStore.GetContactAsync(entry.Address.ContactId);
14 | task0.AsTask().Wait();
15 | return task0.GetResults();
16 | }
17 | else
18 | {
19 | return null;
20 | }
21 | }
22 |
23 | public object ConvertBack(object value, Type targetType, object parameter, string language)
24 | {
25 | throw new NotImplementedException();
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 WOA Project
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Dialer/UI/ViewModel/ViewModelCore.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.UI.Dispatching;
2 | using System.ComponentModel;
3 | using System.Runtime.CompilerServices;
4 |
5 | namespace Dialer.UI.ViewModel
6 | {
7 | public abstract class ViewModelCore : INotifyPropertyChanged
8 | {
9 | protected DispatcherQueue DispatcherQueue
10 | {
11 | get;
12 | }
13 |
14 | public event PropertyChangedEventHandler PropertyChanged;
15 |
16 | protected ViewModelCore(DispatcherQueue dispatcherQueue)
17 | {
18 | DispatcherQueue = dispatcherQueue;
19 | }
20 |
21 | protected virtual void Set(ref T storage, T value, [CallerMemberName] string propertyName = null)
22 | {
23 | if (!Equals(storage, value))
24 | {
25 | storage = value;
26 | OnPropertyChanged(propertyName);
27 | }
28 | }
29 |
30 | protected void OnPropertyChanged(string propertyName)
31 | {
32 | _ = DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Normal, () => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)));
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Dialer/UI/Converters/CallHistoryEntryToCallStateGlyphString.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.UI.Xaml.Data;
2 | using System;
3 | using Windows.ApplicationModel.Calls;
4 |
5 | namespace Dialer.UI.Converters
6 | {
7 | public sealed class CallHistoryEntryToCallStateGlyphString : IValueConverter
8 | {
9 | public static string Convert(PhoneCallHistoryEntry entry)
10 | {
11 | return entry.IsIncoming
12 | ? entry.IsCallerIdBlocked
13 | ? Glyphs.CALL_HISTORY_BLOCKED
14 | : entry.IsMissed ? Glyphs.CALL_HISTORY_MISSED : Glyphs.CALL_HISTORY_INCOMING
15 | : Glyphs.CALL_HISTORY_OUTGOING;
16 | }
17 |
18 | public object Convert(object value, Type targetType, object parameter, string language)
19 | {
20 | return value switch
21 | {
22 | PhoneCallHistoryEntry entry => Convert(entry),
23 | _ => string.Empty,
24 | };
25 | }
26 |
27 | public object ConvertBack(object value, Type targetType, object parameter, string language)
28 | {
29 | throw new NotImplementedException();
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Dialer/UI/Converters/PhoneLineToDisplayNameText.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.UI.Xaml.Data;
2 | using System;
3 | using Windows.ApplicationModel.Calls;
4 |
5 | namespace Dialer.UI.Converters
6 | {
7 | public sealed class PhoneLineToDisplayNameText : IValueConverter
8 | {
9 | public object Convert(object value, Type targetType, object parameter, string language)
10 | {
11 | if (value is PhoneLine line)
12 | {
13 | try
14 | {
15 | return line.DisplayName;
16 | }
17 | catch
18 | {
19 | try
20 | {
21 | return line.NetworkName;
22 | }
23 | catch
24 | {
25 | return string.Empty;
26 | }
27 | }
28 | }
29 | else
30 | {
31 | return string.Empty;
32 | }
33 | }
34 |
35 | public object ConvertBack(object value, Type targetType, object parameter, string language)
36 | {
37 | throw new NotImplementedException();
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Dialer/UI/Converters/Converters.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Dialer/UI/Controls/LinePresenter.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.UI.Xaml;
2 | using Microsoft.UI.Xaml.Controls;
3 | using Microsoft.UI.Xaml.Media;
4 |
5 | namespace Dialer.UI.Controls
6 | {
7 | public sealed partial class LinePresenter : UserControl
8 | {
9 | public static readonly DependencyProperty PresentedLineNameProperty = DependencyProperty.RegisterAttached(nameof(PresentedLineName), typeof(string), typeof(LinePresenter), new PropertyMetadata(null));
10 | public static readonly DependencyProperty PresentedLineIconSourceProperty = DependencyProperty.RegisterAttached(nameof(PresentedLineIconSource), typeof(ImageSource), typeof(LinePresenter), new PropertyMetadata(null));
11 |
12 | public string PresentedLineName
13 | {
14 | get => (string)GetValue(PresentedLineNameProperty);
15 | set => SetValue(PresentedLineNameProperty, value);
16 | }
17 |
18 | public ImageSource PresentedLineIconSource
19 | {
20 | get => (ImageSource)GetValue(PresentedLineIconSourceProperty);
21 | set => SetValue(PresentedLineIconSourceProperty, value);
22 | }
23 |
24 | public LinePresenter()
25 | {
26 | InitializeComponent();
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Dialer/UI/Converters/CallHistoryEntryToCallStateTextString.cs:
--------------------------------------------------------------------------------
1 | using Internal.Windows.Calls;
2 | using Microsoft.UI.Xaml.Data;
3 | using System;
4 | using Windows.ApplicationModel.Calls;
5 |
6 | namespace Dialer.UI.Converters
7 | {
8 | public sealed class CallHistoryEntryToCallStateTextString : IValueConverter
9 | {
10 | public static string Convert(PhoneCallHistoryEntry entry)
11 | {
12 | return entry.IsIncoming
13 | ? entry.IsCallerIdBlocked
14 | ? "Blocked"
15 | : entry.IsMissed ? "Missed" : App.Current.ResourceLoader.GetString(nameof(CallState) + '_' + nameof(CallState.Incoming))
16 | : "Outgoing";
17 | }
18 |
19 | public object Convert(object value, Type targetType, object parameter, string language)
20 | {
21 | return value switch
22 | {
23 | PhoneCallHistoryEntry entry => Convert(entry),
24 | _ => App.Current.ResourceLoader.GetString(nameof(CallState) + "_Unknown"),
25 | };
26 | }
27 |
28 | public object ConvertBack(object value, Type targetType, object parameter, string language)
29 | {
30 | throw new NotImplementedException();
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WoADialer
2 |
3 | A dialer based on UWP and .NET for the WoA on Lumia Project.
4 |
5 | ## Requirements
6 | The UWP requires at least Windows 10 version 1903, build 18362
7 |
8 | ## Building
9 | You'll also need to restore the NuGet packages.
10 |
11 | This is the setup I used:
12 |
13 | - VS 2019
14 | - For the UWP app, the min version is 1809, while the target version is 1903.
15 |
16 | ## Test builds
17 | For early testing you can join to [WOA Dialer Testing Channel](https://t.me/woadialertestingchannel). These builds will not published on GitHub.
18 |
19 | ## This readme
20 | I must have forgot things. Please forgive me and point me to the right directions, and I'll fix it.
21 |
22 | ## This application
23 | I surely have forgot things. I surely have implemented things really badly. Things will be broken for sure. I'm a noob, so open those issues and I'll try to fix them. If you have suggestions on how to improve certain things, feel free to send me a message, do a PR, whatever you want! It's 100% accepted! I'm a student so I have little time to work on side projects, and I still have a lot to learn, so forgive me, please!
24 |
25 | ## Thanks
26 | Thanks a lot for contributing to the project:
27 | - [Ikarago](https://github.com/ikarago)
28 | - [djart](https://github.com/djart)
29 |
--------------------------------------------------------------------------------
/Dialer/UI/Controls/LinePresenter.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Dialer/UI/Converters/DateTimeToString.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.UI.Xaml.Data;
2 | using System;
3 | using System.Globalization;
4 |
5 | namespace Dialer.UI.Converters
6 | {
7 | public sealed class DateTimeToString : IValueConverter
8 | {
9 | public object Convert(object value, Type targetType, object parameter, string language)
10 | {
11 | if (value is DateTime date)
12 | {
13 | try
14 | {
15 | return date.ToString("U", CultureInfo.CurrentCulture);
16 | }
17 | catch
18 | {
19 | return string.Empty;
20 | }
21 | }
22 | if (value is DateTimeOffset dateOffset)
23 | {
24 | try
25 | {
26 | return dateOffset.ToString("F", CultureInfo.CurrentCulture);
27 | }
28 | catch
29 | {
30 | return string.Empty;
31 | }
32 | }
33 | else
34 | {
35 | return string.Empty;
36 | }
37 | }
38 |
39 | public object ConvertBack(object value, Type targetType, object parameter, string language)
40 | {
41 | throw new NotImplementedException();
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/HistoryPage.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Dialer/UI/Controls/CallStatePresenter.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Dialer/UI/Controls/DialPad.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.UI.Xaml.Controls;
2 | using Microsoft.UI.Xaml.Input;
3 | using System;
4 |
5 | namespace Dialer.UI.Controls
6 | {
7 | public sealed partial class DialPad : UserControl
8 | {
9 | public event EventHandler DigitTapped;
10 |
11 | public DialPad()
12 | {
13 | InitializeComponent();
14 | DigitButton[] digitbuttons = { NumPad_0, NumPad_1, NumPad_2, NumPad_3, NumPad_4, NumPad_5, NumPad_6, NumPad_7, NumPad_8, NumPad_9, NumPad_A, NumPad_S };
15 | foreach (DigitButton digitbutton in digitbuttons)
16 | {
17 | digitbutton.Click += Digitbutton_Click;
18 | }
19 | NumPad_0.RightTapped += DigitButton_RightTapped;
20 | }
21 |
22 | private void Digitbutton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
23 | {
24 | if (sender is DigitButton button)
25 | {
26 | DigitTapped?.Invoke(this, button.Digit[0]);
27 | }
28 | }
29 |
30 | private void DigitButton_RightTapped(object sender, RightTappedRoutedEventArgs e)
31 | {
32 | if (sender is DigitButton button)
33 | {
34 | switch (button.Digit)
35 | {
36 | case "0":
37 | DigitTapped?.Invoke(this, '+');
38 | break;
39 | }
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Dialer/UI/Controls/CallStatePresenter.xaml.cs:
--------------------------------------------------------------------------------
1 | using Internal.Windows.Calls;
2 | using Microsoft.UI.Dispatching;
3 | using Microsoft.UI.Xaml;
4 | using Microsoft.UI.Xaml.Controls;
5 |
6 | namespace Dialer.UI.Controls
7 | {
8 | public sealed partial class CallStatePresenter : UserControl
9 | {
10 | public static readonly DependencyProperty PresentedCallProperty = DependencyProperty.RegisterAttached("PresentedCall", typeof(Call), typeof(CallStatePresenter), new PropertyMetadata(null));
11 |
12 | public Call PresentedCall
13 | {
14 | get => (Call)GetValue(PresentedCallProperty);
15 | set
16 | {
17 | if (PresentedCall != value)
18 | {
19 | if (PresentedCall != null)
20 | {
21 | PresentedCall.StateChanged -= PresentedCall_StateChanged;
22 | }
23 | SetValue(PresentedCallProperty, value);
24 | if (value != null)
25 | {
26 | value.StateChanged += PresentedCall_StateChanged;
27 | }
28 | }
29 | }
30 | }
31 |
32 | public CallStatePresenter()
33 | {
34 | InitializeComponent();
35 | }
36 |
37 | private void PresentedCall_StateChanged(Call sender, CallStateChangedEventArgs args)
38 | {
39 | _ = DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Normal, Bindings.Update);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/PhoneLineSettings.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Dialer/UI/ViewModel/AboutViewModel.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.UI.Dispatching;
2 | using Windows.ApplicationModel;
3 |
4 | namespace Dialer.UI.ViewModel
5 | {
6 | public class AboutViewModel : ViewModelCore
7 | {
8 | // Properties
9 | private string _appName;
10 | public string AppName
11 | {
12 | get => _appName;
13 | set => Set(ref _appName, value);
14 | }
15 |
16 | private string _versionNumber;
17 | public string VersionNumber
18 | {
19 | get => _versionNumber;
20 | set => Set(ref _versionNumber, value);
21 | }
22 |
23 |
24 | // Constructor
25 | public AboutViewModel(DispatcherQueue dispatcher) : base(dispatcher)
26 | {
27 | Initialize();
28 | }
29 |
30 | // Initialize Stuff
31 | public void Initialize()
32 | {
33 | AppName = GetAppName();
34 | VersionNumber = GetVersionNumber();
35 | }
36 |
37 |
38 | // Methods
39 | private string GetAppName()
40 | {
41 | Package package = Package.Current;
42 | string appName = package.DisplayName;
43 |
44 | return appName;
45 | }
46 |
47 | private string GetVersionNumber()
48 | {
49 | Package package = Package.Current;
50 | PackageId packageId = package.Id;
51 | PackageVersion version = packageId.Version;
52 |
53 | return $"{version.Major}.{version.Minor}.{version.Build}.{version.Revision}";
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/Dialer/UI/Converters/PageNameToGlyphString.cs:
--------------------------------------------------------------------------------
1 | using Dialer.Systems;
2 | using Microsoft.UI.Xaml.Data;
3 | using System;
4 |
5 | namespace Dialer.UI.Converters
6 | {
7 | public sealed class PageNameToGlyphString : IValueConverter
8 | {
9 | public object Convert(object value, Type targetType, object parameter, string language)
10 | {
11 | return value is string name
12 | ? (object)(name switch
13 | {
14 | UISystem.CALL_HISTORY_PAGE => Glyphs.CALL_PAGE_HISTORY,
15 | UISystem.CALL_UI_PAGE => Glyphs.CALL_PAGE_INCALL,
16 | UISystem.CONTACTS_PAGE => Glyphs.CALL_PAGE_CONTACTS,
17 | UISystem.DIAL_PAGE => Glyphs.CALL_PAGE_DIAL,
18 | UISystem.APPLICATIONS_SETTINGS_PAGE => Glyphs.CALL_SETTINGS_APPS,
19 | UISystem.NOTIFICATIONS_SETTINGS_PAGE => Glyphs.CALL_SETTINGS_NOTIFICATIONS,
20 | UISystem.PERSONALIZATION_SETTINGS_PAGE => Glyphs.CALL_SETTINGS_PERSONALIZATION,
21 | UISystem.PHONE_LINES_SETTINGS_PAGE => Glyphs.CALL_SETTINGS_LINES,
22 | UISystem.SOUND_SETTINGS_PAGE => Glyphs.CALL_SETTINGS_SOUND,
23 | UISystem.ABOUT_SETTINGS_PAGE => Glyphs.CALL_SETTINGS_ABOUT,
24 | _ => string.Empty,
25 | })
26 | : throw new ArgumentException();
27 | }
28 |
29 | public object ConvertBack(object value, Type targetType, object parameter, string language)
30 | {
31 | throw new NotImplementedException();
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/SettingsPage.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Dialer/UI/Glyphs.cs:
--------------------------------------------------------------------------------
1 | namespace Dialer.UI
2 | {
3 | public static class Glyphs
4 | {
5 | public const string NETWORK_TOWER = "\uEC05";
6 | public const string SIM_MISSED = "\uF619";
7 | public const string SIM_LOCK = "\uF61A";
8 | public const string ROAMING_INTERNATIONAL = "\uE878";
9 | public const string NETWORK_OFFLINE = "\uF384";
10 | public const string HANG_UP = "\uE778";
11 | public const string CALL_ENDED = "\uF405";
12 |
13 | public const string CALL_HISTORY_INCOMING = "\uE77E";
14 | public const string CALL_HISTORY_OUTGOING = "\uE77D";
15 | public const string CALL_HISTORY_BLOCKED = "\uEFFA";
16 | public const string CALL_HISTORY_MISSED = "\uEFF8";
17 |
18 | public const string CALL_PAGE_HISTORY = "\uE81C";
19 | public const string CALL_PAGE_DIAL = "\uE75F";
20 | public const string CALL_PAGE_CONTACTS = "\uE1D4";
21 | public const string CALL_PAGE_INCALL = "\uE80B";
22 |
23 | public const string CALL_SETTINGS_APPS = "\uE74C";
24 | public const string CALL_SETTINGS_NOTIFICATIONS = "\uEA8F";
25 | public const string CALL_SETTINGS_PERSONALIZATION = "\uE771";
26 | public const string CALL_SETTINGS_LINES = "\uEC05";
27 | public const string CALL_SETTINGS_SOUND = "\uE15D";
28 | public const string CALL_SETTINGS_ABOUT = "\uE946";
29 |
30 | public const string CALL_INCALL_TALKING = "\uE13A";
31 | public const string CALL_INCALL_DIALING = "\uE80B";
32 | public const string CALL_INCALL_INCOMING = "\uE77E";
33 | public const string CALL_INCALL_ONHOLD = "\uEA68";
34 | public const string CALL_INCALL_TRANSFERRING = "\uED95";
35 | public const string CALL_INCALL_COUNT = "\uE80B";
36 | public const string CALL_INCALL_INDETERMINATE = "\uED97";
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Dialer/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
29 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/Dialer/UI/Controls/AdditionalPhoneContactPresenter.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
22 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Dialer/Systems/DeviceSystem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Threading.Tasks;
4 | using Windows.Devices.Enumeration;
5 | using Windows.Devices.Haptics;
6 | using Windows.Devices.Sensors;
7 |
8 | namespace Dialer.Systems
9 | {
10 | public sealed class DeviceSystem
11 | {
12 | private ProximitySensorDisplayOnOffController DisplayController;
13 |
14 | public ProximitySensor ProximitySensor
15 | {
16 | get; private set;
17 | }
18 | public VibrationDevice VibrationDevice
19 | {
20 | get; private set;
21 | }
22 | public bool IsDisplayControlledByProximitySensor
23 | {
24 | get => DisplayController != null;
25 | set
26 | {
27 | if (value && DisplayController == null)
28 | {
29 | DisplayController = ProximitySensor?.CreateDisplayOnOffController();
30 | }
31 | else if (!value && DisplayController != null)
32 | {
33 | DisplayController.Dispose();
34 | DisplayController = null;
35 | }
36 | }
37 | }
38 |
39 | public DeviceSystem()
40 | {
41 | }
42 |
43 | public async Task Initialize()
44 | {
45 | try
46 | {
47 | if (App.Current.PermissionSystem.Vibration == VibrationAccessStatus.Allowed)
48 | {
49 | VibrationDevice = await VibrationDevice.GetDefaultAsync();
50 | }
51 | DeviceInformation proximityDevice = (await DeviceInformation.FindAllAsync(ProximitySensor.GetDeviceSelector())).FirstOrDefault();
52 | if (proximityDevice != null)
53 | {
54 | ProximitySensor = ProximitySensor.FromId(proximityDevice.Id);
55 | }
56 | }
57 | catch
58 | {
59 | }
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Dialer/UI/Controls/SmallCallPresenter.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/PersonalizationSettings.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
16 |
18 |
21 |
22 |
23 |
27 |
28 |
32 |
36 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Dialer/UI/Converters/CallToCallStateGlyphString.cs:
--------------------------------------------------------------------------------
1 | using Internal.Windows.Calls;
2 | using Microsoft.UI.Xaml.Data;
3 | using System;
4 |
5 | namespace Dialer.UI.Converters
6 | {
7 | public sealed class CallToCallStateGlyphString : IValueConverter
8 | {
9 | public object Convert(object value, Type targetType, object parameter, string language)
10 | {
11 | return value switch
12 | {
13 | Call call => call.State switch
14 | {
15 | CallState.ActiveTalking => Glyphs.CALL_INCALL_TALKING,
16 | CallState.Dialing => Glyphs.CALL_INCALL_DIALING,
17 | CallState.Disconnected => call.StateReason switch
18 | {
19 | CallStateReason.NetworkCongestion => Glyphs.NETWORK_TOWER,
20 | CallStateReason.CallBarred => Glyphs.SIM_MISSED,
21 | CallStateReason.FDNRestricted => Glyphs.SIM_LOCK,
22 | CallStateReason.RoamRestricted => Glyphs.ROAMING_INTERNATIONAL,
23 | CallStateReason.ServiceOff => Glyphs.NETWORK_OFFLINE,
24 | CallStateReason.Other or CallStateReason.Ended => Glyphs.CALL_ENDED,
25 | CallStateReason.Dropped or CallStateReason.CallUpgradeInitiated or CallStateReason.Busy or CallStateReason.VideoCallingOff => Glyphs.HANG_UP,
26 | _ => string.Empty,
27 | },
28 | CallState.Incoming => Glyphs.CALL_INCALL_INCOMING,
29 | CallState.OnHold => Glyphs.CALL_INCALL_ONHOLD,
30 | CallState.Transferring => Glyphs.CALL_INCALL_TRANSFERRING,
31 | CallState.Count => Glyphs.CALL_INCALL_COUNT,
32 | CallState.Indeterminate => Glyphs.CALL_INCALL_INDETERMINATE,
33 | _ => string.Empty,
34 | },
35 | _ => string.Empty,
36 | };
37 | }
38 |
39 | public object ConvertBack(object value, Type targetType, object parameter, string language)
40 | {
41 | throw new NotImplementedException();
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Dialer/Helpers/RelayCommand.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Input;
3 |
4 | namespace Dialer.Helpers
5 | {
6 | // Originally generated by the Windows Template Studio https://github.com/microsoft/windowsTemplateStudio
7 | public class RelayCommand : ICommand
8 | {
9 | private readonly Action _execute;
10 |
11 | private readonly Func _canExecute;
12 |
13 | public event EventHandler CanExecuteChanged;
14 |
15 | public RelayCommand(Action execute)
16 | : this(execute, null)
17 | {
18 | }
19 |
20 | public RelayCommand(Action execute, Func canExecute)
21 | {
22 | _execute = execute ?? throw new ArgumentNullException(nameof(execute));
23 | _canExecute = canExecute;
24 | }
25 |
26 | public bool CanExecute(object parameter)
27 | {
28 | return _canExecute == null || _canExecute();
29 | }
30 |
31 | public void Execute(object parameter)
32 | {
33 | _execute();
34 | }
35 |
36 | public void OnCanExecuteChanged()
37 | {
38 | CanExecuteChanged?.Invoke(this, EventArgs.Empty);
39 | }
40 | }
41 |
42 | public class RelayCommand : ICommand
43 | {
44 | private readonly Action _execute;
45 |
46 | private readonly Func _canExecute;
47 |
48 | public event EventHandler CanExecuteChanged;
49 |
50 | public RelayCommand(Action execute)
51 | : this(execute, null)
52 | {
53 | }
54 |
55 | public RelayCommand(Action execute, Func canExecute)
56 | {
57 | _execute = execute ?? throw new ArgumentNullException(nameof(execute));
58 | _canExecute = canExecute;
59 | }
60 |
61 | public bool CanExecute(object parameter)
62 | {
63 | return _canExecute == null || _canExecute((T)parameter);
64 | }
65 |
66 | public void Execute(object parameter)
67 | {
68 | _execute((T)parameter);
69 | }
70 |
71 | public void OnCanExecuteChanged()
72 | {
73 | CanExecuteChanged?.Invoke(this, EventArgs.Empty);
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/Dialer/UI/Controls/SmallCallPresenter.xaml.cs:
--------------------------------------------------------------------------------
1 | using Internal.Windows.Calls;
2 | using Microsoft.UI.Dispatching;
3 | using Microsoft.UI.Xaml;
4 | using Microsoft.UI.Xaml.Controls;
5 | using System;
6 | using System.Threading;
7 |
8 | namespace Dialer.UI.Controls
9 | {
10 | public sealed partial class SmallCallPresenter : UserControl
11 | {
12 | public static readonly DependencyProperty PresentedCallProperty = DependencyProperty.RegisterAttached("PresentedCall", typeof(Call), typeof(CallStatePresenter), new PropertyMetadata(null));
13 |
14 | private Timer Timer;
15 |
16 | public Call PresentedCall
17 | {
18 | get => (Call)GetValue(PresentedCallProperty);
19 | set
20 | {
21 | if (PresentedCall != value)
22 | {
23 | if (PresentedCall != null)
24 | {
25 | PresentedCall.StateChanged -= PresentedCall_StateChanged;
26 | }
27 | SetValue(PresentedCallProperty, value);
28 | if (value != null)
29 | {
30 | value.StateChanged += PresentedCall_StateChanged;
31 | PresentedCall_StateChanged(value, new CallStateChangedEventArgs(value.State, value.State, value.StateReason));
32 | }
33 | }
34 | }
35 | }
36 |
37 | public SmallCallPresenter()
38 | {
39 | InitializeComponent();
40 | }
41 |
42 | private void PresentedCall_StateChanged(Call sender, CallStateChangedEventArgs args)
43 | {
44 | switch (args.NewState)
45 | {
46 | case CallState.Disconnected:
47 | case CallState.Count:
48 | case CallState.Indeterminate:
49 | Timer?.Dispose();
50 | break;
51 | case CallState.ActiveTalking:
52 | Timer = new Timer(TimerCallback, null, TimeSpan.Zero, new TimeSpan(0, 0, 1));
53 | break;
54 | }
55 | }
56 |
57 | private void TimerCallback(object state)
58 | {
59 | _ = DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Normal, Bindings.Update);
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Dialer/Dialer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net7.0-windows10.0.22621
4 | preview
5 | WinExe
6 | en-US
7 | 10.0.17763.0
8 | False
9 | True
10 | Always
11 | arm64
12 | 0
13 | OnApplicationRun
14 | True
15 | 0
16 | SHA256
17 | true
18 | app.manifest
19 | true
20 | x86;x64;ARM64
21 | win10-$(Platform).pubxml
22 | win10-x86;win10-x64;win10-arm64
23 | False
24 | True
25 | D:\Certificates\WOL\woldevdialersw2020.pfx
26 |
27 |
28 |
29 | Designer
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
25 |
26 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Dialer/UI/Converters/CallHistoryEntryToLineDisplayNameText.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.UI.Xaml.Data;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using Windows.ApplicationModel.Calls;
6 | using Windows.Foundation;
7 | using Windows.System;
8 |
9 | namespace Dialer.UI.Converters
10 | {
11 | public sealed class CallHistoryEntryToLineDisplayNameText : IValueConverter
12 | {
13 | public object Convert(object value, Type targetType, object parameter, string language)
14 | {
15 | if (value is PhoneCallHistoryEntry entry)
16 | {
17 | try
18 | {
19 | switch (entry.RemoteId)
20 | {
21 | case string celluarID when celluarID.StartsWith(nameof(PhoneLineTransport.Cellular)):
22 | celluarID = celluarID.Split('|')[1];
23 | return App.Current.CallSystem.DisplayableLines.First(x => x.Line.Id == Guid.Parse(celluarID)).DisplayName;
24 | case string appID when appID.StartsWith(nameof(PhoneLineTransport.VoipApp)):
25 | appID = appID.Split('|')[1];
26 | IAsyncOperation> task1 = AppDiagnosticInfo.RequestInfoForPackageAsync(appID);
27 | task1.AsTask().Wait();
28 | return task1.GetResults()[0].AppInfo.DisplayInfo.DisplayName;
29 | case string deviceID when deviceID.StartsWith(nameof(PhoneLineTransport.Bluetooth)):
30 | //deviceID = deviceID.Split('|')[1];
31 | //IAsyncOperation task2 = DeviceInformation.CreateFromIdAsync(deviceID);
32 | //task2.AsTask().Wait();
33 | //return task2.GetResults().Name;
34 | default:
35 | return string.Empty;
36 | }
37 | }
38 | catch
39 | {
40 | return string.Empty;
41 | }
42 | }
43 | else
44 | {
45 | return string.Empty;
46 | }
47 | }
48 |
49 | public object ConvertBack(object value, Type targetType, object parameter, string language)
50 | {
51 | throw new NotImplementedException();
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Dialer/Helpers/SettingsManager.cs:
--------------------------------------------------------------------------------
1 | using Windows.Storage;
2 |
3 | namespace Dialer.Helpers
4 | {
5 | internal static class SettingsManager
6 | {
7 | public static bool isFirstTimeRun()
8 | {
9 | return getNumberFormatting()?.Length == 0 || getNumberFormatting() == null || getNumberFormatting()?.Length == 0;
10 | }
11 |
12 | public static void setDefaultSettings()
13 | {
14 | setDialPadSize("Tall");
15 | setNumberFormatting("None");
16 | setProximitySensorOn(true);
17 | }
18 |
19 | public static string getNumberFormatting()
20 | {
21 | ApplicationDataContainer roamingSettings = ApplicationData.Current.RoamingSettings;
22 | string currentNumberFormatting = roamingSettings.Values["numberFormatting"] as string;
23 | return currentNumberFormatting;
24 | }
25 |
26 | public static string getDialPadSize()
27 | {
28 | ApplicationDataContainer roamingSettings = ApplicationData.Current.RoamingSettings;
29 | string currentDialPadSize = roamingSettings.Values["dialpadSize"] as string;
30 | return currentDialPadSize;
31 | }
32 |
33 | public static bool getProximitySensorOn()
34 | {
35 | ApplicationDataContainer roamingSettings = ApplicationData.Current.RoamingSettings;
36 | if (roamingSettings.Values["proximitySensorOn"] == null)
37 | {
38 | setProximitySensorOn(true);
39 | }
40 |
41 | return (bool)roamingSettings.Values["proximitySensorOn"];
42 | }
43 |
44 | public static void setNumberFormatting(string newFormatting)
45 | {
46 | //maybe check if the newFormatting is a valid value
47 | ApplicationDataContainer roamingSettings = ApplicationData.Current.RoamingSettings;
48 | roamingSettings.Values["numberFormatting"] = newFormatting;
49 | }
50 |
51 | public static void setDialPadSize(string newDialPadSize)
52 | {
53 | //maybe check if the newDialPadSize is a valid value
54 | ApplicationDataContainer roamingSettings = ApplicationData.Current.RoamingSettings;
55 | roamingSettings.Values["dialpadSize"] = newDialPadSize;
56 | }
57 |
58 | public static void setProximitySensorOn(bool on)
59 | {
60 | ApplicationDataContainer roamingSettings = ApplicationData.Current.RoamingSettings;
61 | roamingSettings.Values["proximitySensorOn"] = on;
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Dialer/UI/Controls/VerticalIndexScrollbar.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 | #
15 | A
16 | B
17 | C
18 | D
19 | E
20 | F
21 | G
22 | H
23 | I
24 | J
25 | K
26 | L
27 | M
28 | N
29 | O
30 | P
31 | Q
32 | R
33 | S
34 | T
35 | U
36 | V
37 | W
38 | X
39 | Y
40 | Z
41 | ?
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/Dialer/UI/Controls/VerticalIndexScrollbar.xaml.cs:
--------------------------------------------------------------------------------
1 | using Dialer.UI.Pages;
2 | using Microsoft.UI.Xaml;
3 | using Microsoft.UI.Xaml.Controls;
4 | using Microsoft.UI.Xaml.Input;
5 | using System;
6 |
7 | namespace Dialer.UI.Controls
8 | {
9 | public sealed partial class VerticalIndexScrollbar : UserControl
10 | {
11 | private bool TrackingPointer = false;
12 |
13 | public VerticalIndexScrollbar()
14 | {
15 | InitializeComponent();
16 | }
17 |
18 | public void FixSpacing()
19 | {
20 | LettersStackPanel.Spacing = (LettersStackPanel.ActualHeight / 26d) - 21d;
21 | }
22 |
23 | private void Letter_Tapped(object sender, TappedRoutedEventArgs e)
24 | {
25 | //ContactsPage.CurrentInstance?.NavigateToLetter((sender as TextBlock).Text);
26 | }
27 |
28 | private void LettersStackPanel_PointerPressed(object sender, PointerRoutedEventArgs e)
29 | {
30 | //Debug.WriteLine("Pointer entered at " + e.GetCurrentPoint(sender as UIElement).Position);
31 | TrackingPointer = true;
32 | double h = e.GetCurrentPoint(sender as UIElement).Position.Y;
33 | //Calculate letter based on point position
34 | int index = (int)Math.Floor(h / (referenceTB.ActualHeight + LettersStackPanel.Spacing));
35 | //Debug.WriteLine("Pointer should be in letter " + Convert.ToChar(64 + index));
36 | ContactsPage.CurrentInstance?.NavigateToLetter(Convert.ToChar(64 + index).ToString());
37 | }
38 |
39 | private void LettersStackPanel_PointerMoved(object sender, PointerRoutedEventArgs e)
40 | {
41 | if (TrackingPointer)
42 | {
43 | //Debug.WriteLine("Pointer moved at " + e.GetCurrentPoint(sender as UIElement).Position);
44 | double h = e.GetCurrentPoint(sender as UIElement).Position.Y;
45 | //Calculate letter based on point position
46 | int index = (int)Math.Floor(h / (referenceTB.ActualHeight + LettersStackPanel.Spacing));
47 | //Debug.WriteLine("Pointer should be in letter " + Convert.ToChar(64 + index));
48 | ContactsPage.CurrentInstance?.NavigateToLetter(Convert.ToChar(64 + index).ToString());
49 | }
50 | }
51 |
52 | private void LettersStackPanel_PointerReleased(object sender, PointerRoutedEventArgs e)
53 | {
54 | //Debug.WriteLine("Pointer exited at " + e.GetCurrentPoint(sender as UIElement).Position);
55 | TrackingPointer = false;
56 | double h = e.GetCurrentPoint(sender as UIElement).Position.Y;
57 | //Calculate letter based on point position
58 | int index = (int)Math.Floor(h / (referenceTB.ActualHeight + LettersStackPanel.Spacing));
59 | //Debug.WriteLine("Pointer should be in letter " + Convert.ToChar(64 + index));
60 | ContactsPage.CurrentInstance?.NavigateToLetter(Convert.ToChar(64 + index).ToString());
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/ContactsPage.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | A
35 |
36 |
37 |
38 |
39 |
40 | Loading contact list...
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Dialer/UI/Controls/DialPad.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/ApplicationsSettings.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
17 |
19 |
22 |
23 |
24 |
28 |
29 |
33 |
36 |
39 |
42 |
43 |
44 |
45 |
46 |
47 |
49 |
51 |
54 |
55 |
58 | Turn off the phone screen when you put your phone close to your face during a call (uses proximity sensor)
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/Dialer.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.0.31423.177
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dialer", "Dialer\Dialer.csproj", "{51BB3779-D2B9-49B5-AF9D-9838E114A869}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Internal.Windows.Calls", "Internal.Windows.Calls\Internal.Windows.Calls\Internal.Windows.Calls.csproj", "{35E52B56-36F5-4820-8626-8547FEFD7666}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|ARM64 = Debug|ARM64
13 | Debug|x64 = Debug|x64
14 | Debug|x86 = Debug|x86
15 | Release|ARM64 = Release|ARM64
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {51BB3779-D2B9-49B5-AF9D-9838E114A869}.Debug|ARM64.ActiveCfg = Debug|ARM64
21 | {51BB3779-D2B9-49B5-AF9D-9838E114A869}.Debug|ARM64.Build.0 = Debug|ARM64
22 | {51BB3779-D2B9-49B5-AF9D-9838E114A869}.Debug|ARM64.Deploy.0 = Debug|ARM64
23 | {51BB3779-D2B9-49B5-AF9D-9838E114A869}.Debug|x64.ActiveCfg = Debug|x64
24 | {51BB3779-D2B9-49B5-AF9D-9838E114A869}.Debug|x64.Build.0 = Debug|x64
25 | {51BB3779-D2B9-49B5-AF9D-9838E114A869}.Debug|x64.Deploy.0 = Debug|x64
26 | {51BB3779-D2B9-49B5-AF9D-9838E114A869}.Debug|x86.ActiveCfg = Debug|x86
27 | {51BB3779-D2B9-49B5-AF9D-9838E114A869}.Debug|x86.Build.0 = Debug|x86
28 | {51BB3779-D2B9-49B5-AF9D-9838E114A869}.Debug|x86.Deploy.0 = Debug|x86
29 | {51BB3779-D2B9-49B5-AF9D-9838E114A869}.Release|ARM64.ActiveCfg = Release|ARM64
30 | {51BB3779-D2B9-49B5-AF9D-9838E114A869}.Release|ARM64.Build.0 = Release|ARM64
31 | {51BB3779-D2B9-49B5-AF9D-9838E114A869}.Release|ARM64.Deploy.0 = Release|ARM64
32 | {51BB3779-D2B9-49B5-AF9D-9838E114A869}.Release|x64.ActiveCfg = Release|x64
33 | {51BB3779-D2B9-49B5-AF9D-9838E114A869}.Release|x64.Build.0 = Release|x64
34 | {51BB3779-D2B9-49B5-AF9D-9838E114A869}.Release|x64.Deploy.0 = Release|x64
35 | {51BB3779-D2B9-49B5-AF9D-9838E114A869}.Release|x86.ActiveCfg = Release|x86
36 | {51BB3779-D2B9-49B5-AF9D-9838E114A869}.Release|x86.Build.0 = Release|x86
37 | {51BB3779-D2B9-49B5-AF9D-9838E114A869}.Release|x86.Deploy.0 = Release|x86
38 | {35E52B56-36F5-4820-8626-8547FEFD7666}.Debug|ARM64.ActiveCfg = Debug|ARM64
39 | {35E52B56-36F5-4820-8626-8547FEFD7666}.Debug|ARM64.Build.0 = Debug|ARM64
40 | {35E52B56-36F5-4820-8626-8547FEFD7666}.Debug|x64.ActiveCfg = Debug|x64
41 | {35E52B56-36F5-4820-8626-8547FEFD7666}.Debug|x64.Build.0 = Debug|x64
42 | {35E52B56-36F5-4820-8626-8547FEFD7666}.Debug|x86.ActiveCfg = Debug|x86
43 | {35E52B56-36F5-4820-8626-8547FEFD7666}.Debug|x86.Build.0 = Debug|x86
44 | {35E52B56-36F5-4820-8626-8547FEFD7666}.Release|ARM64.ActiveCfg = Release|ARM64
45 | {35E52B56-36F5-4820-8626-8547FEFD7666}.Release|ARM64.Build.0 = Release|ARM64
46 | {35E52B56-36F5-4820-8626-8547FEFD7666}.Release|x64.ActiveCfg = Release|x64
47 | {35E52B56-36F5-4820-8626-8547FEFD7666}.Release|x64.Build.0 = Release|x64
48 | {35E52B56-36F5-4820-8626-8547FEFD7666}.Release|x86.ActiveCfg = Release|x86
49 | {35E52B56-36F5-4820-8626-8547FEFD7666}.Release|x86.Build.0 = Release|x86
50 | EndGlobalSection
51 | GlobalSection(SolutionProperties) = preSolution
52 | HideSolutionNode = FALSE
53 | EndGlobalSection
54 | GlobalSection(ExtensibilityGlobals) = postSolution
55 | SolutionGuid = {E806CFC3-147E-42BD-B0EC-E26A5EE405F7}
56 | EndGlobalSection
57 | EndGlobal
58 |
--------------------------------------------------------------------------------
/Dialer/UI/Converters/CallToCallStateTextString.cs:
--------------------------------------------------------------------------------
1 | using Internal.Windows.Calls;
2 | using Microsoft.UI.Xaml.Data;
3 | using System;
4 |
5 | namespace Dialer.UI.Converters
6 | {
7 | public sealed class CallToCallStateTextString : IValueConverter
8 | {
9 | public static string Convert(Call call)
10 | {
11 | return call.State switch
12 | {
13 | CallState.ActiveTalking => App.Current.ResourceLoader.GetString(nameof(CallState) + '_' + nameof(CallState.ActiveTalking)),
14 | CallState.Dialing => App.Current.ResourceLoader.GetString(nameof(CallState) + '_' + nameof(CallState.Dialing)),
15 | CallState.Disconnected => call.StateReason switch
16 | {
17 | CallStateReason.Busy => App.Current.ResourceLoader.GetString(nameof(CallState) + '_' + nameof(CallStateReason.Busy)),
18 | CallStateReason.CallBarred => App.Current.ResourceLoader.GetString(nameof(CallState) + '_' + nameof(CallStateReason.CallBarred)),
19 | CallStateReason.CallUpgradeInitiated => App.Current.ResourceLoader.GetString(nameof(CallState) + '_' + nameof(CallStateReason.CallUpgradeInitiated)),
20 | CallStateReason.Dropped => App.Current.ResourceLoader.GetString(nameof(CallState) + '_' + nameof(CallStateReason.Dropped)),
21 | CallStateReason.Ended => App.Current.ResourceLoader.GetString(nameof(CallState) + '_' + nameof(CallStateReason.Ended)),
22 | CallStateReason.FDNRestricted => App.Current.ResourceLoader.GetString(nameof(CallState) + '_' + nameof(CallStateReason.FDNRestricted)),
23 | CallStateReason.NetworkCongestion => App.Current.ResourceLoader.GetString(nameof(CallState) + '_' + nameof(CallStateReason.NetworkCongestion)),
24 | CallStateReason.RoamRestricted => App.Current.ResourceLoader.GetString(nameof(CallState) + '_' + nameof(CallStateReason.RoamRestricted)),
25 | CallStateReason.ServiceOff => App.Current.ResourceLoader.GetString(nameof(CallState) + '_' + nameof(CallStateReason.ServiceOff)),
26 | CallStateReason.VideoCallingOff => App.Current.ResourceLoader.GetString(nameof(CallState) + '_' + nameof(CallStateReason.Busy)),
27 | _ => App.Current.ResourceLoader.GetString(nameof(CallState) + '_' + nameof(CallState.Disconnected)),
28 | },
29 | CallState.Incoming => App.Current.ResourceLoader.GetString(nameof(CallState) + '_' + nameof(CallState.Incoming)),
30 | CallState.Indeterminate => App.Current.ResourceLoader.GetString(nameof(CallState) + '_' + nameof(CallState.Indeterminate)),
31 | CallState.OnHold => App.Current.ResourceLoader.GetString(nameof(CallState) + '_' + nameof(CallState.OnHold)),
32 | CallState.Transferring => App.Current.ResourceLoader.GetString(nameof(CallState) + '_' + nameof(CallState.Transferring)),
33 | CallState.Count => App.Current.ResourceLoader.GetString(nameof(CallState) + '_' + nameof(CallState.Count)),
34 | _ => App.Current.ResourceLoader.GetString(nameof(CallState) + "_Unknown"),
35 | };
36 | }
37 |
38 | public object Convert(object value, Type targetType, object parameter, string language)
39 | {
40 | return value switch
41 | {
42 | Call call => Convert(call),
43 | _ => App.Current.ResourceLoader.GetString(nameof(CallState) + "_Unknown"),
44 | };
45 | }
46 |
47 | public object ConvertBack(object value, Type targetType, object parameter, string language)
48 | {
49 | throw new NotImplementedException();
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Dialer/UI/Converters/CallHistoryEntryToLineIconBitmap.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.UI.Xaml.Data;
2 | using Microsoft.UI.Xaml.Media.Imaging;
3 | using System;
4 | using System.Collections.Generic;
5 | using Windows.ApplicationModel;
6 | using Windows.ApplicationModel.Calls;
7 | using Windows.ApplicationModel.Core;
8 | using Windows.Foundation;
9 | using Windows.Storage.Streams;
10 | using Windows.System;
11 |
12 | namespace Dialer.UI.Converters
13 | {
14 | public sealed class CallHistoryEntryToLineIconBitmap : IValueConverter
15 | {
16 | public object Convert(object value, Type targetType, object parameter, string language)
17 | {
18 | if (value is PhoneCallHistoryEntry entry)
19 | {
20 | try
21 | {
22 | IRandomAccessStream stream;
23 | switch (entry.RemoteId)
24 | {
25 | case string celluarID when celluarID.StartsWith(nameof(PhoneLineTransport.Cellular)):
26 | celluarID = celluarID.Split('|')[1];
27 | IAsyncOperation task0 = PhoneLine.FromIdAsync(Guid.Parse(celluarID));
28 | task0.AsTask().Wait();
29 | IAsyncOperation> task3 = Package.Current.GetAppListEntriesAsync();
30 | task3.AsTask().Wait();
31 | IAsyncOperation task2 = task3.GetResults()[0].DisplayInfo.GetLogo(new Size(512, 512)).OpenReadAsync();
32 | task2.AsTask().Wait();
33 | stream = task2.GetResults();
34 | break;
35 | case string appID when appID.StartsWith(nameof(PhoneLineTransport.VoipApp)):
36 | appID = appID.Split('|')[1];
37 | IAsyncOperation> task1 = AppDiagnosticInfo.RequestInfoForPackageAsync(appID);
38 | task1.AsTask().Wait();
39 | task2 = task1.GetResults()[0].AppInfo.DisplayInfo.GetLogo(new Size(512, 512)).OpenReadAsync();
40 | task2.AsTask().Wait();
41 | stream = task2.GetResults();
42 | break;
43 | case string deviceID when deviceID.StartsWith(nameof(PhoneLineTransport.Bluetooth)):
44 | //deviceID = deviceID.Split('|')[1];
45 | //task0 = PhoneLine.FromIdAsync(Guid.Parse(deviceID));
46 | //task0.AsTask().Wait();
47 | //IAsyncOperation task3 = DeviceInformation.CreateFromIdAsync(task0.GetResults().TransportDeviceId);
48 | //task3.AsTask().Wait();
49 | //IAsyncOperation task4 = task3.GetResults().GetThumbnailAsync();
50 | //task4.AsTask().Wait();
51 | //stream = task4.GetResults();
52 | //break;
53 | default:
54 | return null;
55 | }
56 | BitmapImage a = new();
57 | a.SetSource(stream);
58 | return a;
59 | }
60 | catch
61 | {
62 | return null;
63 | }
64 | }
65 | else
66 | {
67 | return null;
68 | }
69 | }
70 |
71 | public object ConvertBack(object value, Type targetType, object parameter, string language)
72 | {
73 | throw new NotImplementedException();
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/Dialer/UI/Controls/ContactControl.xaml:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/Dialer/UI/Controls/ContactControl.xaml.cs:
--------------------------------------------------------------------------------
1 | using Dialer.Systems;
2 | using Dialer.UI.Pages;
3 | using Microsoft.UI.Xaml;
4 | using Microsoft.UI.Xaml.Controls;
5 | using Microsoft.UI.Xaml.Input;
6 | using Microsoft.UI.Xaml.Media.Imaging;
7 | using System;
8 | using System.Collections.Generic;
9 | using System.Collections.ObjectModel;
10 | using Windows.ApplicationModel.Calls;
11 | using Windows.ApplicationModel.Contacts;
12 | using Windows.Storage.Streams;
13 |
14 | namespace Dialer.UI.Controls
15 | {
16 | public sealed partial class ContactControl : UserControl
17 | {
18 | private List> additionalPhoneContacts;
19 | private readonly ObservableCollection additionalPhoneContactPresenters;
20 |
21 | public Contact AssociatedContact;
22 |
23 | public string ContactName
24 | {
25 | get => ContactNameTB.Text;
26 | set => ContactNameTB.Text = value;
27 | }
28 |
29 | public string ContactMainPhone
30 | {
31 | get => ContactMainPhoneTB.Text;
32 | set => ContactMainPhoneTB.Text = value;
33 | }
34 |
35 | public List> AdditionalContactPhones
36 | {
37 | get => additionalPhoneContacts;
38 | set
39 | {
40 | additionalPhoneContacts = value;
41 | foreach (Tuple additionalPhone in value)
42 | {
43 | AdditionalPhoneContactPresenter apcp = new()
44 | {
45 | PhoneType = additionalPhone.Item1,
46 | PhoneNumber = additionalPhone.Item2
47 | };
48 | additionalPhoneContactPresenters.Add(apcp);
49 | }
50 | }
51 | }
52 |
53 | private async void SetContactPicture(IRandomAccessStreamReference randomAccessStreamReference)
54 | {
55 | try
56 | {
57 | BitmapImage bitmapImage = new();
58 | using IRandomAccessStreamWithContentType valueStream = await randomAccessStreamReference.OpenReadAsync();
59 | bitmapImage.SetSource(valueStream);
60 | ContactImage.ImageSource = bitmapImage;
61 | }
62 | catch
63 | {
64 | ContactImage.ImageSource = new BitmapImage(new Uri("ms-appx:///Assets//NoContactIcon.png"));
65 | }
66 | }
67 |
68 | public IRandomAccessStreamReference ContactPicture
69 | {
70 | set => SetContactPicture(value);
71 | }
72 |
73 | public ContactControl()
74 | {
75 | InitializeComponent();
76 | additionalPhoneContactPresenters = new ObservableCollection();
77 | }
78 |
79 | private void MainCallButton_Tapped(object sender, TappedRoutedEventArgs e)
80 | {
81 | //TODO: Check for missing phone lines. If no phone lines, show an alert
82 | try
83 | {
84 | App.Current.CallSystem.DefaultLine?.DialWithOptions(new PhoneDialOptions() { Number = ContactMainPhone });
85 | }
86 | catch { }
87 | }
88 |
89 | private async void FlyoutDeleteContact_Click(object sender, RoutedEventArgs e)
90 | {
91 | await ContactSystem.DeleteContact(AssociatedContact);
92 | ContactsPage.CurrentInstance.RemoveContactControl(this);
93 | }
94 |
95 | private void FlyoutCallContact_Click(object sender, RoutedEventArgs e)
96 | {
97 | try
98 | {
99 | App.Current.CallSystem.DefaultLine?.DialWithOptions(new PhoneDialOptions() { Number = ContactMainPhone });
100 | }
101 | catch { }
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/Dialer/UI/Controls/CallHistoryEntryPresenter.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/Dialer/UI/Controls/TitlebarControl.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
40 |
41 |
48 |
49 |
56 |
57 |
58 |
65 |
66 |
71 |
72 |
77 |
78 |
84 |
85 |
94 |
95 |
--------------------------------------------------------------------------------
/Dialer/Systems/ContactSystem.cs:
--------------------------------------------------------------------------------
1 | using Dialer.UI.Controls;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Collections.ObjectModel;
5 | using System.Diagnostics;
6 | using System.Threading.Tasks;
7 | using Windows.ApplicationModel.Contacts;
8 |
9 | namespace Dialer.Systems
10 | {
11 | internal static class ContactSystem
12 | {
13 | private static ContactStore _contactStore;
14 | private static ObservableCollection _contacts;
15 | private static ObservableCollection _contactControls;
16 |
17 | public static event EventHandler ContactsLoaded;
18 |
19 | public static bool ContactsLoading = false;
20 |
21 | public static ObservableCollection Contacts => _contacts ?? null;
22 |
23 | public static ObservableCollection ContactControls => _contactControls ?? null;
24 |
25 | public static async void LoadContacts()
26 | {
27 | if (_contacts == null && !ContactsLoading)
28 | {
29 | try
30 | {
31 | ContactsLoading = true;
32 | _contactStore = await ContactManager.RequestStoreAsync();
33 | ObservableCollection t_contacts = new(await _contactStore.FindContactsAsync());
34 |
35 | Debug.WriteLine("Found " + t_contacts.Count + " contacts");
36 |
37 | ObservableCollection t_contactControls = new();
38 |
39 | foreach (Contact contact in t_contacts)
40 | {
41 | ContactControl cc = new()
42 | {
43 | AssociatedContact = contact,
44 | ContactName = contact.DisplayName
45 | };
46 | if (contact.Phones.Count == 0)
47 | {
48 | continue;
49 | }
50 |
51 | cc.ContactMainPhone = contact.Phones[0].Number;
52 | List> additionalPhones = new();
53 | foreach (ContactPhone contactPhone in contact.Phones)
54 | {
55 | additionalPhones.Add(new Tuple(contactPhone.Kind.ToString(), contactPhone.Number));
56 | }
57 | cc.AdditionalContactPhones = additionalPhones;
58 | if (contact.SmallDisplayPicture != null)
59 | {
60 | //TODO: Fix wrong cast
61 | cc.ContactPicture = contact.SmallDisplayPicture;
62 | }
63 |
64 | t_contactControls.Add(cc);
65 | }
66 | _contacts = t_contacts;
67 | _contactControls = t_contactControls;
68 | }
69 | catch
70 | {
71 | }
72 |
73 | ContactsLoading = false;
74 |
75 | ContactsLoaded?.Invoke(null, EventArgs.Empty);
76 | }
77 | }
78 |
79 | public static async Task DeleteContact(Contact contact)
80 | {
81 | ContactStore cs = await ContactManager.RequestStoreAsync();
82 | ContactList cl = null;
83 | try
84 | {
85 | cl = await cs.GetContactListAsync(contact.ContactListId);
86 | }
87 | catch
88 | {
89 | IReadOnlyList contactlists = await cs.FindContactListsAsync();
90 | foreach (ContactList _cl in contactlists)
91 | {
92 | try
93 | {
94 | if (_cl.GetContactAsync(contact.Id) != null)
95 | {
96 | cl = _cl;
97 | }
98 | }
99 | catch { }
100 | }
101 | }
102 | if (cl == null)
103 | {
104 | return; //For some reason the correct contact list can't be retrieved. It should be in Contact.ContactListId, but...
105 | }
106 |
107 | await cl.DeleteContactAsync(contact);
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/Dialer/Systems/PermissionSystem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using Windows.ApplicationModel.Calls;
4 | using Windows.ApplicationModel.Contacts;
5 | using Windows.Devices.Haptics;
6 | using Windows.System;
7 | using Windows.UI.Notifications.Management;
8 |
9 | namespace Dialer.Systems
10 | {
11 | public sealed class PermissionSystem
12 | {
13 | public VibrationAccessStatus? Vibration
14 | {
15 | get; private set;
16 | }
17 | public UserNotificationListenerAccessStatus? Notifications
18 | {
19 | get; private set;
20 | }
21 | public DiagnosticAccessStatus? Diagnostic
22 | {
23 | get; private set;
24 | }
25 | public bool? CallHistory
26 | {
27 | get; private set;
28 | }
29 | public bool? Contacts
30 | {
31 | get; private set;
32 | }
33 | public bool? Calling
34 | {
35 | get; private set;
36 | }
37 | public bool IsAllPermissionsObtained
38 | {
39 | get
40 | {
41 | bool result = true;
42 | result &= Notifications == UserNotificationListenerAccessStatus.Allowed;
43 | result &= Diagnostic == DiagnosticAccessStatus.Allowed;
44 | result &= CallHistory ?? false;
45 | result &= Contacts ?? false;
46 | result &= Calling ?? false;
47 | return result;
48 | }
49 | }
50 |
51 | public PermissionSystem()
52 | {
53 | }
54 |
55 | public async Task RequestAllPermissions()
56 | {
57 | bool result = true;
58 | result &= await RequestVibrationAccess();
59 | result &= await RequestNotificationsAccess();
60 | result &= await RequestDiagnosticAccess();
61 | result &= await RequestContactsAccess();
62 | result &= await RequestCallingAccess();
63 | result &= await RequestCallHistoryAccess();
64 | return result;
65 | }
66 |
67 | public async Task RequestVibrationAccess()
68 | {
69 | try
70 | {
71 | Vibration = await VibrationDevice.RequestAccessAsync();
72 | }
73 | catch
74 | {
75 | Vibration = null;
76 | }
77 | return Vibration.HasValue;
78 | }
79 |
80 | public async Task RequestNotificationsAccess()
81 | {
82 | try
83 | {
84 | Notifications = await UserNotificationListener.Current.RequestAccessAsync();
85 | }
86 | catch
87 | {
88 | Notifications = null;
89 | }
90 | return Notifications.HasValue;
91 | }
92 |
93 | public async Task RequestDiagnosticAccess()
94 | {
95 | try
96 | {
97 | Diagnostic = await AppDiagnosticInfo.RequestAccessAsync();
98 | }
99 | catch
100 | {
101 | Diagnostic = null;
102 | }
103 | return Diagnostic.HasValue;
104 | }
105 |
106 | public async Task RequestCallingAccess()
107 | {
108 | try
109 | {
110 | Calling = await PhoneCallManager.RequestStoreAsync() is not null;
111 | }
112 | catch
113 | {
114 | Calling = null;
115 | }
116 | return Calling.HasValue;
117 | }
118 |
119 | public async Task RequestCallHistoryAccess()
120 | {
121 | try
122 | {
123 | CallHistory = await PhoneCallHistoryManager.RequestStoreAsync(PhoneCallHistoryStoreAccessType.AllEntriesReadWrite) is not null;
124 | }
125 | catch
126 | {
127 | CallHistory = null;
128 | }
129 | return CallHistory.HasValue;
130 | }
131 |
132 | public async Task RequestContactsAccess()
133 | {
134 | try
135 | {
136 | Contacts = await ContactManager.RequestStoreAsync(ContactStoreAccessType.AllContactsReadOnly) is not null;
137 | }
138 | catch
139 | {
140 | Contacts = null;
141 | }
142 | return Contacts.HasValue;
143 | }
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/ContactsPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using Dialer.Systems;
2 | using Dialer.UI.Controls;
3 | using Microsoft.UI.Dispatching;
4 | using Microsoft.UI.Xaml.Controls;
5 | using Microsoft.UI.Xaml.Navigation;
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Collections.ObjectModel;
9 | using System.Diagnostics;
10 | using System.Linq;
11 | using System.Threading;
12 | using System.Threading.Tasks;
13 |
14 | namespace Dialer.UI.Pages
15 | {
16 | public sealed partial class ContactsPage : Page
17 | {
18 | private Timer _hideHintTimer;
19 | private ObservableCollection _contactControls;
20 |
21 | public static ContactsPage CurrentInstance;
22 |
23 | public ContactsPage()
24 | {
25 | InitializeComponent();
26 |
27 | _contactControls = new ObservableCollection();
28 | CurrentInstance = this;
29 | }
30 |
31 | protected override void OnNavigatedTo(NavigationEventArgs e)
32 | {
33 | base.OnNavigatedTo(e);
34 | SizeChanged += ContactsPage_SizeChanged;
35 |
36 | LoadingGrid.Visibility = Microsoft.UI.Xaml.Visibility.Visible;
37 |
38 | _ = Task.Run(Aaa); //TODO: This still hangs the UI in some cases 🥲
39 | }
40 |
41 | private void Aaa()
42 | {
43 | if (ContactSystem.ContactControls == null)
44 | {
45 | ContactSystem.ContactsLoaded += (object sender, EventArgs e) => LoadDataCompleted();
46 | }
47 | else
48 | {
49 | LoadDataCompleted();
50 | }
51 | }
52 |
53 | private void LoadDataCompleted()
54 | {
55 | _ = DispatcherQueue.TryEnqueue(DispatcherQueuePriority.High, () =>
56 | {
57 | ContactsItemsControl.ItemsSource = null;
58 | _contactControls = ContactSystem.ContactControls;
59 | ContactsItemsControl.ItemsSource = _contactControls;
60 | LoadingGrid.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed;
61 | });
62 | }
63 |
64 | private void ContactsPage_SizeChanged(object sender, Microsoft.UI.Xaml.SizeChangedEventArgs e)
65 | {
66 | viScrollbar.FixSpacing();
67 | }
68 |
69 | public void NavigateToLetter(string letter)
70 | {
71 | ScrollLetterHint.Text = letter;
72 | if (ScrollLetterGrid.Visibility == Microsoft.UI.Xaml.Visibility.Collapsed)
73 | {
74 | ScrollLetterHintShow.Begin();
75 | }
76 |
77 | ScrollLetterGrid.Visibility = Microsoft.UI.Xaml.Visibility.Visible;
78 | if (_hideHintTimer != null)
79 | {
80 | _ = _hideHintTimer.Change(Timeout.Infinite, Timeout.Infinite);
81 | _hideHintTimer.Dispose();
82 | _hideHintTimer = null;
83 | }
84 |
85 | IEnumerable ContactsWithLetter = from contact in _contactControls where contact.ContactName.ToUpper().StartsWith(letter) select contact;
86 |
87 | try
88 | {
89 | ContactsWithLetter.First().StartBringIntoView();
90 | }
91 | catch
92 | {
93 | //TODO: Fix for missing letter -> move to previous/next letter
94 | }
95 |
96 | _hideHintTimer = new Timer((state) =>
97 | {
98 | _ = DispatcherQueue.TryEnqueue(DispatcherQueuePriority.High, () =>
99 | {
100 | ScrollLetterHintHide.Begin();
101 | ScrollLetterHintHide.Completed += (object sender, object e) =>
102 | {
103 | _ = DispatcherQueue.TryEnqueue(DispatcherQueuePriority.High, () => ScrollLetterGrid.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed);
104 |
105 | if (_hideHintTimer != null)
106 | {
107 | _ = _hideHintTimer.Change(Timeout.Infinite, Timeout.Infinite);
108 | _hideHintTimer.Dispose();
109 | _hideHintTimer = null;
110 | }
111 | };
112 | });
113 | }, null, 1000, 1000);
114 |
115 | Debug.WriteLine("Got request to navigate to letter " + letter);
116 | }
117 |
118 | public void RemoveContactControl(ContactControl cc)
119 | {
120 | _ = _contactControls.Remove(cc);
121 | }
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/Dialer/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
19 |
20 |
21 |
22 |
23 | Dialer
24 | LumiaWOA
25 | Assets\StoreLogo.png
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
40 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | Dialer
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | Dialer.exe
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using Dialer.Systems;
2 | using Microsoft.UI.Xaml;
3 | using Microsoft.UI.Xaml.Controls;
4 | using Microsoft.UI.Xaml.Input;
5 | using Microsoft.UI.Xaml.Media.Animation;
6 | using Microsoft.UI.Xaml.Navigation;
7 | using System;
8 | using System.Collections.Specialized;
9 | using Windows.System;
10 |
11 | namespace Dialer.UI.Pages
12 | {
13 | public sealed partial class MainPage : Page
14 | {
15 | public UISystem UISystem => App.Current.UISystem;
16 |
17 | public MainPage()
18 | {
19 | InitializeComponent();
20 | }
21 |
22 | protected override void OnNavigatedTo(NavigationEventArgs e)
23 | {
24 | base.OnNavigatedTo(e);
25 | switch (e.Parameter)
26 | {
27 | case string number:
28 | Navigate(UISystem.DIAL_PAGE, new EntranceNavigationTransitionInfo(), number);
29 | break;
30 | }
31 | }
32 |
33 | private void NavView_Loaded(object sender, RoutedEventArgs e)
34 | {
35 | // Add handler for ContentFrame navigation.
36 | ContentFrame.Navigated += On_Navigated;
37 |
38 | // Add keyboard accelerators for backwards navigation.
39 | KeyboardAccelerator goBack = new()
40 | {
41 | Key = VirtualKey.GoBack
42 | };
43 | goBack.Invoked += BackInvoked;
44 | KeyboardAccelerators.Add(goBack);
45 |
46 | // ALT routes here
47 | KeyboardAccelerator altLeft = new()
48 | {
49 | Key = VirtualKey.Left,
50 | Modifiers = VirtualKeyModifiers.Menu
51 | };
52 | altLeft.Invoked += BackInvoked;
53 | KeyboardAccelerators.Add(altLeft);
54 | }
55 |
56 | private void NavView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
57 | {
58 | if (args.IsSettingsSelected)
59 | {
60 | Navigate("SettingsPage", args.RecommendedNavigationTransitionInfo);
61 | }
62 | else if (args.SelectedItemContainer != null)
63 | {
64 | string navItemTag = args.SelectedItemContainer.Tag.ToString();
65 | Navigate(navItemTag, args.RecommendedNavigationTransitionInfo);
66 | }
67 | else
68 | {
69 | _ = ContentFrame.Navigate(UISystem.PageNameToType(args.SelectedItem.ToString()));
70 | }
71 | }
72 |
73 | public void Navigate(string navItemTag, NavigationTransitionInfo transitionInfo, object parameter = null)
74 | {
75 | Type _page = UISystem.PageNameToType(navItemTag);
76 |
77 | // Get the page type before navigation so you can prevent duplicate
78 | // entries in the backstack.
79 | Type preNavPageType = ContentFrame.CurrentSourcePageType;
80 |
81 | // Only navigate if the selected page isn't currently loaded.
82 | if (_page is not null && !Equals(preNavPageType, _page))
83 | {
84 | nv_PagePresenter.SelectedItem = navItemTag;
85 | _ = ContentFrame.Navigate(_page, parameter, transitionInfo);
86 | }
87 | }
88 |
89 | private void NavView_BackRequested(NavigationView sender, NavigationViewBackRequestedEventArgs args)
90 | {
91 | _ = On_BackRequested();
92 | }
93 |
94 | private void BackInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
95 | {
96 | _ = On_BackRequested();
97 | args.Handled = true;
98 | }
99 |
100 | private bool On_BackRequested()
101 | {
102 | if (!ContentFrame.CanGoBack)
103 | {
104 | return false;
105 | }
106 |
107 | // Don't go back if the nav pane is overlayed.
108 | if (nv_PagePresenter.IsPaneOpen &&
109 | (nv_PagePresenter.DisplayMode == NavigationViewDisplayMode.Compact ||
110 | nv_PagePresenter.DisplayMode == NavigationViewDisplayMode.Minimal))
111 | {
112 | return false;
113 | }
114 |
115 | ContentFrame.GoBack();
116 | return true;
117 | }
118 |
119 | private void On_Navigated(object sender, NavigationEventArgs e)
120 | {
121 | nv_PagePresenter.IsBackEnabled = ContentFrame.CanGoBack;
122 | }
123 |
124 | private void Page_Loaded(object sender, RoutedEventArgs e)
125 | {
126 | UISystem.MainPagePages.CollectionChanged += MainPagePages_CollectionChanged;
127 | }
128 |
129 | private void MainPagePages_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
130 | {
131 | if (e.NewItems?.Contains(UISystem.CALL_UI_PAGE) ?? false)
132 | {
133 | Navigate(UISystem.CALL_UI_PAGE, new EntranceNavigationTransitionInfo());
134 | }
135 | else if (e.OldItems?.Contains(UISystem.CALL_UI_PAGE) ?? false)
136 | {
137 | Navigate(UISystem.CALL_HISTORY_PAGE, new EntranceNavigationTransitionInfo());
138 | ContentFrame.BackStack.Clear();
139 | }
140 | }
141 |
142 | private void Page_Unloaded(object sender, RoutedEventArgs e)
143 | {
144 | UISystem.MainPagePages.CollectionChanged -= MainPagePages_CollectionChanged;
145 | }
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/DialPage.xaml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
41 |
42 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
77 |
78 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
115 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/Dialer/App.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | 0,0,0,48
13 | 0,0,0,24
14 | 0,0,0,16
15 | 0,0,0,12
16 |
17 |
18 |
19 |
23 |
24 |
25 |
26 |
30 |
31 |
32 |
33 |
37 |
38 |
46 |
47 |
48 |
52 |
53 |
54 |
55 |
59 |
60 |
63 |
64 |
65 |
66 |
70 |
71 |
74 |
75 |
76 |
77 |
80 |
81 |
82 |
83 |
87 |
88 |
91 |
92 |
93 |
96 |
97 |
98 |
99 |
100 |
106 |
107 |
108 |
109 |
110 |
--------------------------------------------------------------------------------
/Dialer/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using Dialer.UI.Pages;
2 | using Microsoft.UI;
3 | using Microsoft.UI.Windowing;
4 | using Microsoft.UI.Xaml;
5 | using Microsoft.UI.Xaml.Controls;
6 | using Microsoft.UI.Xaml.Media;
7 | using System;
8 | using System.Collections.Generic;
9 | using System.Runtime.InteropServices;
10 | using WinRT.Interop;
11 |
12 | // To learn more about WinUI, the WinUI project structure,
13 | // and more about our project templates, see: http://aka.ms/winui-project-info.
14 |
15 | namespace Dialer
16 | {
17 | ///
18 | /// An empty window that can be used on its own or navigated to within a Frame.
19 | ///
20 | public sealed partial class MainWindow : Window
21 | {
22 | private readonly AppWindow m_AppWindow;
23 |
24 | public MainWindow()
25 | {
26 | InitializeComponent();
27 |
28 | m_AppWindow = GetAppWindowForCurrentWindow();
29 |
30 | // Check to see if customization is supported.
31 | // Currently only supported on Windows 11.
32 | if (AppWindowTitleBar.IsCustomizationSupported())
33 | {
34 | AppWindowTitleBar titleBar = m_AppWindow.TitleBar;
35 | titleBar.ExtendsContentIntoTitleBar = true;
36 | AppTitleBar.Loaded += AppTitleBar_Loaded;
37 | AppTitleBar.SizeChanged += AppTitleBar_SizeChanged;
38 |
39 | BackButton.Click += OnBackClicked;
40 | BackButton.Visibility = Visibility.Collapsed;
41 | }
42 | else
43 | {
44 | // Title bar customization using these APIs is currently
45 | // supported only on Windows 11. In other cases, hide
46 | // the custom title bar element.
47 | // AppTitleBar.Visibility = Visibility.Collapsed;
48 | // TODO Show alternative UI for any functionality in
49 | // the title bar, such as the back button, if used
50 | }
51 |
52 | WinUIEx.WindowManager.Get(this).Backdrop = new WinUIEx.MicaSystemBackdrop();
53 | }
54 |
55 | public Button BackButton => AppTitleBarBackButton;
56 |
57 | private void AppTitleBar_Loaded(object sender, RoutedEventArgs e)
58 | {
59 | SetTitleBar(AppTitleBar);
60 | // TODO Rename MainPage in case your app Main Page has a different name
61 | _ = PageFrame.Navigate(typeof(MainPage));
62 | if (AppWindowTitleBar.IsCustomizationSupported())
63 | {
64 | SetDragRegionForCustomTitleBar(m_AppWindow);
65 | }
66 | }
67 |
68 | private void OnBackClicked(object sender, RoutedEventArgs e)
69 | {
70 | if (PageFrame.CanGoBack)
71 | {
72 | PageFrame.GoBack();
73 | }
74 | }
75 |
76 | private void AppTitleBar_SizeChanged(object sender, SizeChangedEventArgs e)
77 | {
78 | if (AppWindowTitleBar.IsCustomizationSupported()
79 | && m_AppWindow.TitleBar.ExtendsContentIntoTitleBar)
80 | {
81 | // Update drag region if the size of the title bar changes.
82 | SetDragRegionForCustomTitleBar(m_AppWindow);
83 | }
84 | }
85 |
86 | private AppWindow GetAppWindowForCurrentWindow()
87 | {
88 | IntPtr hWnd = WindowNative.GetWindowHandle(this);
89 | WindowId wndId = Win32Interop.GetWindowIdFromWindow(hWnd);
90 | return AppWindow.GetFromWindowId(wndId);
91 | }
92 |
93 | private void SetDragRegionForCustomTitleBar(AppWindow appWindow)
94 | {
95 | if (AppWindowTitleBar.IsCustomizationSupported()
96 | && appWindow.TitleBar.ExtendsContentIntoTitleBar)
97 | {
98 | double scaleAdjustment = GetScaleAdjustment();
99 |
100 | RightPaddingColumn.Width = new GridLength(appWindow.TitleBar.RightInset / scaleAdjustment);
101 | LeftPaddingColumn.Width = new GridLength(appWindow.TitleBar.LeftInset / scaleAdjustment);
102 |
103 | List dragRectsList = new();
104 |
105 | Windows.Graphics.RectInt32 dragRectL;
106 | dragRectL.X = (int)((LeftPaddingColumn.ActualWidth + IconColumn.ActualWidth) * scaleAdjustment);
107 | dragRectL.Y = 0;
108 | dragRectL.Height = (int)(AppTitleBar.ActualHeight * scaleAdjustment);
109 | dragRectL.Width = (int)((TitleColumn.ActualWidth
110 | + DragColumn.ActualWidth) * scaleAdjustment);
111 | dragRectsList.Add(dragRectL);
112 |
113 | Windows.Graphics.RectInt32[] dragRects = dragRectsList.ToArray();
114 | appWindow.TitleBar.SetDragRectangles(dragRects);
115 | }
116 | }
117 |
118 | [DllImport("Shcore.dll", SetLastError = true)]
119 | internal static extern int GetDpiForMonitor(IntPtr hmonitor, Monitor_DPI_Type dpiType, out uint dpiX, out uint dpiY);
120 |
121 | internal enum Monitor_DPI_Type : int
122 | {
123 | MDT_Effective_DPI = 0,
124 | MDT_Angular_DPI = 1,
125 | MDT_Raw_DPI = 2,
126 | MDT_Default = MDT_Effective_DPI
127 | }
128 |
129 | private double GetScaleAdjustment()
130 | {
131 | IntPtr hWnd = WindowNative.GetWindowHandle(this);
132 | WindowId wndId = Win32Interop.GetWindowIdFromWindow(hWnd);
133 | DisplayArea displayArea = DisplayArea.GetFromWindowId(wndId, DisplayAreaFallback.Primary);
134 | IntPtr hMonitor = Win32Interop.GetMonitorFromDisplayId(displayArea.DisplayId);
135 |
136 | // Get DPI.
137 | int result = GetDpiForMonitor(hMonitor, Monitor_DPI_Type.MDT_Default, out uint dpiX, out uint _);
138 | if (result != 0)
139 | {
140 | throw new Exception("Could not get DPI for monitor.");
141 | }
142 |
143 | uint scaleFactorPercent = (uint)((((long)dpiX * 100) + (96 >> 1)) / 96);
144 | return scaleFactorPercent / 100.0;
145 | }
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/Dialer/Systems/BackgroundSystem.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.WinUI.Notifications;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Windows.ApplicationModel.Background;
7 | using Windows.ApplicationModel.Calls.Background;
8 | using Windows.UI.Notifications;
9 |
10 | namespace Dialer.Systems
11 | {
12 | public sealed class BackgroundSystem
13 | {
14 | private const string CALL_BLOCKED = "CallBlocked";
15 | private const string CALL_HISTORY_CHANGED = "CallHistoryChanged";
16 | private const string CALL_ORIGIN_DATA_REQUEST = "CallOriginDataRequest";
17 | private const string LINE_STATE_CHANGED = "LineStateChanged";
18 | //private const string NEW_VOICEMAIL_MESSAGE = "NewVoicemailMessage";
19 | private const string TOAST_BACKGROUNG_ACTIVATED = "ToastBackgroungActivated";
20 |
21 | private bool Skip = false;
22 |
23 | public BackgroundSystem()
24 | {
25 | }
26 |
27 | private async Task ConfigureBackgroundTasks(bool force = false)
28 | {
29 | _ = await BackgroundExecutionManager.RequestAccessAsync();
30 | Dictionary taskRegistration = new()
31 | {
32 | { CALL_BLOCKED, false },
33 | { CALL_HISTORY_CHANGED, false },
34 | { CALL_ORIGIN_DATA_REQUEST, false },
35 | //{ NEW_VOICEMAIL_MESSAGE, false },
36 | { LINE_STATE_CHANGED, false },
37 | { TOAST_BACKGROUNG_ACTIVATED, false },
38 | };
39 | foreach (IBackgroundTaskRegistration registeredTask in BackgroundTaskRegistration.AllTasks.Select(x => x.Value))
40 | {
41 | switch (registeredTask.Name)
42 | {
43 | case string taskName when taskRegistration.Keys.Contains(taskName):
44 | if (force)
45 | {
46 | goto default;
47 | }
48 | else
49 | {
50 | taskRegistration[taskName] = true;
51 | }
52 | break;
53 | default:
54 | registeredTask.Unregister(false);
55 | break;
56 | }
57 | }
58 | foreach (string taskName in taskRegistration.Keys)
59 | {
60 | if (!taskRegistration[taskName])
61 | {
62 | BackgroundTaskBuilder taskBuilder = new()
63 | {
64 | Name = taskName,
65 | TaskEntryPoint = "Dialer.App" // Maybe we need to use .SetTaskEntryPointClsid like the notification sample..
66 | };
67 | switch (taskName)
68 | {
69 | case CALL_BLOCKED:
70 | taskBuilder.SetTrigger(new PhoneTrigger(PhoneTriggerType.CallBlocked, false));
71 | break;
72 | case CALL_HISTORY_CHANGED:
73 | taskBuilder.SetTrigger(new PhoneTrigger(PhoneTriggerType.CallHistoryChanged, false));
74 | break;
75 | case CALL_ORIGIN_DATA_REQUEST:
76 | taskBuilder.SetTrigger(new PhoneTrigger(PhoneTriggerType.CallOriginDataRequest, false));
77 | break;
78 | /*case NEW_VOICEMAIL_MESSAGE:
79 | taskBuilder.SetTrigger(new PhoneTrigger(PhoneTriggerType.NewVoicemailMessage, false));
80 | break;*/
81 | case LINE_STATE_CHANGED:
82 | taskBuilder.SetTrigger(new PhoneTrigger(PhoneTriggerType.LineChanged, false));
83 | break;
84 | case TOAST_BACKGROUNG_ACTIVATED:
85 | taskBuilder.SetTrigger(new ToastNotificationActionTrigger());
86 | break;
87 | default:
88 | throw new NotImplementedException($"Case for {taskName} task missed.");
89 | }
90 | _ = taskBuilder.Register();
91 | }
92 | }
93 | }
94 |
95 | private void OnLateBackgroundActivation()
96 | {
97 | App.Current.NotificationSystem.RemoveSystemToastNotificationIfExist();
98 | App.Current.NotificationSystem.RefreshCallNotification(App.Current.CallSystem.CallManager.CurrentCalls);
99 | }
100 |
101 | public async Task Initialize()
102 | {
103 | await ConfigureBackgroundTasks();
104 | }
105 |
106 | public void OnBackgroundActivated(IBackgroundTaskInstance taskInstance)
107 | {
108 | switch (taskInstance.Task.Name)
109 | {
110 | case CALL_ORIGIN_DATA_REQUEST:
111 | //PhoneCallOriginDataRequestTriggerDetails originDataRequest = args.TaskInstance.TriggerDetails as PhoneCallOriginDataRequestTriggerDetails;
112 | //PhoneCallOrigin data = new PhoneCallOrigin();
113 | //data.Category = "Category";
114 | //data.CategoryDescription = "CategoryDescription";
115 | //data.DisplayName = "DisplayName";
116 | //data.Location = "Location";
117 | //PhoneCallOriginManager.SetCallOrigin(originDataRequest.RequestId, data);
118 | break;
119 | case LINE_STATE_CHANGED:
120 | _ = taskInstance.TriggerDetails as PhoneLineChangedTriggerDetails;
121 | if (!Skip && !App.Current.IsForeground)
122 | {
123 | Skip = true;
124 | OnLateBackgroundActivation();
125 | }
126 | break;
127 | case TOAST_BACKGROUNG_ACTIVATED:
128 | ToastNotificationActionTriggerDetail toastDetails = taskInstance.TriggerDetails as ToastNotificationActionTriggerDetail;
129 | App.Current.OnToastNotificationActivated(ToastActivationType.Background, toastDetails.Argument);
130 | break;
131 | }
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/AboutSettings.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
27 |
28 |
31 |
35 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
50 |
51 |
52 |
53 |
55 |
58 |
61 |
62 |
63 |
66 |
67 |
68 |
69 |
70 |
72 |
74 |
77 |
78 |
79 |
80 |
84 |
85 |
86 |
89 |
90 |
91 |
94 |
95 |
96 |
99 |
100 |
101 |
104 |
105 |
106 |
107 |
108 |
109 |
111 |
113 |
116 |
117 |
118 |
119 |
120 |
122 |
123 |
127 |
128 |
130 |
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/Dialer/UI/Controls/TitlebarControl.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.UI.Windowing;
2 | using Microsoft.UI.Xaml;
3 | using Microsoft.UI.Xaml.Controls;
4 | using Microsoft.UI.Xaml.Media;
5 | using System;
6 | using System.Diagnostics;
7 | using Windows.ApplicationModel;
8 | using Windows.ApplicationModel.Core;
9 | using Windows.UI;
10 | using Windows.UI.Core;
11 | using WinUIEx;
12 |
13 | #nullable enable
14 |
15 | namespace Dialer.UI.Controls
16 | {
17 | public sealed partial class TitlebarControl : UserControl
18 | {
19 | private static string AppName = Package.Current.DisplayName;
20 |
21 | public event EventHandler BackButtonClick;
22 |
23 | private AppWindow GetForCurrentView()
24 | {
25 | // Retrieve the window handle (HWND) of the current (XAML) WinUI 3 window.
26 | nint hWnd = HwndExtensions.GetActiveWindow();
27 |
28 | // Retrieve the WindowId that corresponds to hWnd.
29 | Microsoft.UI.WindowId windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
30 |
31 | // Lastly, retrieve the AppWindow for the current (XAML) WinUI 3 window.
32 | return AppWindow.GetFromWindowId(windowId);
33 | }
34 |
35 | private string GetAppTitle()
36 | {
37 | AppWindow appWindow = GetForCurrentView();
38 |
39 | return (!string.IsNullOrEmpty(
40 | appWindow?.Title) ?
41 | appWindow!.Title + " - " : "") +
42 | AppName;
43 | }
44 |
45 | private string AppTitle = "";
46 |
47 | public TitlebarControl()
48 | {
49 | InitializeComponent();
50 | Loaded += TitleBarControl_Loaded;
51 |
52 | if (AppWindowTitleBar.IsCustomizationSupported())
53 | {
54 | AppWindowTitleBar titlebar = GetForCurrentView().TitleBar;
55 | if (titlebar != null)
56 | {
57 | App.Window.SetTitleBar(TitlebarCanvas);
58 |
59 | titlebar.ExtendsContentIntoTitleBar = true;
60 | Height = titlebar.Height != 0 ? titlebar.Height : 0;
61 |
62 | Thickness margin = CustomTitleBar.Margin;
63 | margin.Right = titlebar.RightInset;
64 | CustomTitleBar.Margin = margin;
65 | }
66 | }
67 |
68 | #if DEBUG
69 | if (Debugger.IsAttached)
70 | {
71 | RedIndicator.Visibility = Visibility.Visible;
72 | }
73 | else
74 | {
75 | AttachDebuggerButton.Visibility = Visibility.Visible;
76 | }
77 |
78 | if (Application.Current.DebugSettings.FailFastOnErrors)
79 | {
80 | YellowIndicator.Visibility = Visibility.Visible;
81 | }
82 | #endif
83 |
84 | RefreshColor();
85 | }
86 |
87 | private void Back_Click(object sender, RoutedEventArgs e)
88 | {
89 | BackButtonClick?.Invoke(this, e);
90 | }
91 |
92 | public void RefreshColor()
93 | {
94 | if (AppWindowTitleBar.IsCustomizationSupported())
95 | {
96 | AppWindowTitleBar titlebar = GetForCurrentView().TitleBar;
97 | if (titlebar != null)
98 | {
99 | SolidColorBrush transparentColorBrush = new()
100 | {
101 | Opacity = 0
102 | };
103 | Color transparentColor = transparentColorBrush.Color;
104 |
105 | titlebar.BackgroundColor = transparentColor;
106 | titlebar.ButtonBackgroundColor = transparentColor;
107 | titlebar.InactiveBackgroundColor = transparentColor;
108 | titlebar.ButtonInactiveBackgroundColor = transparentColor;
109 |
110 | SolidColorBrush foregroundThemeBrush = (SolidColorBrush)Resources["ApplicationForegroundThemeBrush"];
111 |
112 | titlebar.ButtonForegroundColor = foregroundThemeBrush.Color;
113 | titlebar.ForegroundColor = foregroundThemeBrush.Color;
114 |
115 | Color color = foregroundThemeBrush.Color;
116 | color.A = 16;
117 | titlebar.InactiveForegroundColor = color;
118 | titlebar.ButtonInactiveForegroundColor = color;
119 |
120 | Color hovercolor = foregroundThemeBrush.Color;
121 | hovercolor.A = 32;
122 | titlebar.ButtonHoverBackgroundColor = hovercolor;
123 | titlebar.ButtonHoverForegroundColor = foregroundThemeBrush.Color;
124 | hovercolor.A = 64;
125 | titlebar.ButtonPressedBackgroundColor = hovercolor;
126 | titlebar.ButtonPressedForegroundColor = foregroundThemeBrush.Color;
127 | }
128 | }
129 | }
130 |
131 | private async void TitleBarControl_Loaded(object sender, RoutedEventArgs e)
132 | {
133 | try
134 | {
135 | AppName = (await Package.Current.GetAppListEntriesAsync())[0].DisplayInfo.DisplayName;
136 | }
137 | catch { }
138 |
139 | AppTitle = GetAppTitle();
140 | #if DEBUG
141 | AppTitle += " [DEBUG]";
142 | #endif
143 | WindowTitle.Text = AppTitle;
144 | }
145 |
146 | private void TitleBar_LayoutMetricsChanged(CoreApplicationViewTitleBar sender, object args)
147 | {
148 | Height = sender.Height != 0 ? sender.Height : 0;
149 | Thickness margin = CustomTitleBar.Margin;
150 | margin.Right = sender.SystemOverlayRightInset;
151 | CustomTitleBar.Margin = margin;
152 | }
153 |
154 | private void TitleBar_IsVisibleChanged(CoreApplicationViewTitleBar sender, object args)
155 | {
156 | SetVisibility(sender.IsVisible);
157 | }
158 |
159 | private void SetVisibility(bool IsVisible)
160 | {
161 | Visibility = IsVisible ? Visibility.Visible : Visibility.Collapsed;
162 | }
163 |
164 | private AppViewBackButtonVisibility _BackButtonVisibility = AppViewBackButtonVisibility.Collapsed;
165 |
166 | public AppViewBackButtonVisibility BackButtonVisibility
167 | {
168 | get => _BackButtonVisibility;
169 | set
170 | {
171 | _BackButtonVisibility = value;
172 | switch (_BackButtonVisibility)
173 | {
174 | case AppViewBackButtonVisibility.Visible:
175 | BackButton.Visibility = Visibility.Visible;
176 | break;
177 |
178 | case AppViewBackButtonVisibility.Collapsed:
179 | BackButton.Visibility = Visibility.Collapsed;
180 | break;
181 | }
182 | }
183 | }
184 |
185 | public void UpdateTitle()
186 | {
187 | AppTitle = GetAppTitle();
188 | #if DEBUG
189 | AppTitle += " [DEBUG]";
190 | #endif
191 | WindowTitle.Text = AppTitle;
192 | }
193 |
194 | public string Title
195 | {
196 | get =>
197 | GetAppTitle();
198 | set
199 | {
200 | GetForCurrentView().Title = value;
201 | AppTitle = (!string.IsNullOrEmpty(value) ?
202 | value + " - " : "") +
203 | AppName;
204 |
205 | #if DEBUG
206 | AppTitle += " [DEBUG]";
207 | #endif
208 | WindowTitle.Text = AppTitle;
209 | }
210 | }
211 |
212 | private void AttachDebuggerButton_Click(object sender, RoutedEventArgs e)
213 | {
214 | _ = Debugger.Launch();
215 |
216 | if (Debugger.IsAttached)
217 | {
218 | RedIndicator.Visibility = Visibility.Visible;
219 |
220 | AttachDebuggerButton.Visibility = Visibility.Collapsed;
221 | }
222 | else
223 | {
224 | AttachDebuggerButton.Visibility = Visibility.Visible;
225 | }
226 |
227 | if (Application.Current.DebugSettings.FailFastOnErrors)
228 | {
229 | YellowIndicator.Visibility = Visibility.Visible;
230 | }
231 | }
232 | }
233 | }
--------------------------------------------------------------------------------
/Dialer/UI/Pages/CallUIPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using Dialer.Helpers;
2 | using Internal.Windows.Calls;
3 | using Microsoft.UI.Dispatching;
4 | using Microsoft.UI.Xaml;
5 | using Microsoft.UI.Xaml.Controls;
6 | using Microsoft.UI.Xaml.Navigation;
7 | using System;
8 | using System.Threading;
9 | using Windows.ApplicationModel.Calls;
10 | using Windows.Graphics;
11 | using WinUIEx;
12 |
13 | namespace Dialer.UI.Pages
14 | {
15 | public sealed partial class CallUIPage : Page
16 | {
17 | public CallManager CallManager => App.Current.CallSystem.CallManager;
18 |
19 | private Timer Timer;
20 | private Call PresentedCall;
21 |
22 | public CallUIPage()
23 | {
24 | InitializeComponent();
25 |
26 | // Retrieve the window handle (HWND) of the current (XAML) WinUI 3 window.
27 | nint hWnd = HwndExtensions.GetActiveWindow();
28 |
29 | // Retrieve the WindowId that corresponds to hWnd.
30 | Microsoft.UI.WindowId windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
31 |
32 | // Lastly, retrieve the AppWindow for the current (XAML) WinUI 3 window.
33 | Microsoft.UI.Windowing.AppWindow appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
34 |
35 | if (appWindow != null)
36 | {
37 | // You now have an AppWindow object, and you can call its methods to manipulate the window.
38 | //appWindow.SetPreferredMinSize(new Size { Width = 400, Height = 100 });
39 | //appWindow.Resize(new Size { Width = 400, Height = 100 });
40 | }
41 |
42 | if (CallManager.ActiveCall != null)
43 | {
44 | PresentedCall = CallManager.ActiveCall;
45 | PresentedCall.StateChanged += PresentedCall_StateChanged;
46 | PresentedCall_StateChanged(PresentedCall, new CallStateChangedEventArgs(PresentedCall.State, PresentedCall.State, PresentedCall.StateReason));
47 | }
48 |
49 | CallManager.ActiveCallChanged += CallManager_ActiveCallChanged;
50 | }
51 |
52 | private void CallManager_ActiveCallChanged(CallManager sender, Call args)
53 | {
54 | if (PresentedCall != null)
55 | {
56 | PresentedCall.StateChanged -= PresentedCall_StateChanged;
57 | }
58 | if (CallManager.ActiveCall != null)
59 | {
60 | PresentedCall = CallManager.ActiveCall;
61 | PresentedCall.StateChanged += PresentedCall_StateChanged;
62 | PresentedCall_StateChanged(PresentedCall, new CallStateChangedEventArgs(PresentedCall.State, PresentedCall.State, PresentedCall.StateReason));
63 | }
64 | }
65 |
66 | private void PresentedCall_StateChanged(Call sender, CallStateChangedEventArgs args)
67 | {
68 | switch (args.NewState)
69 | {
70 | case CallState.Disconnected:
71 | case CallState.Count:
72 | case CallState.Indeterminate:
73 | Timer?.Dispose();
74 | break;
75 | case CallState.ActiveTalking:
76 | Timer = new Timer(TimerCallback, null, TimeSpan.Zero, new TimeSpan(0, 0, 1));
77 | break;
78 | }
79 | }
80 |
81 | private void TimerCallback(object state)
82 | {
83 | _ = DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Normal, Bindings.Update);
84 | }
85 |
86 | private void ResizeView(SizeInt32 size)
87 | {
88 | // Retrieve the window handle (HWND) of the current (XAML) WinUI 3 window.
89 | nint hWnd = HwndExtensions.GetActiveWindow();
90 |
91 | // Retrieve the WindowId that corresponds to hWnd.
92 | Microsoft.UI.WindowId windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
93 |
94 | // Lastly, retrieve the AppWindow for the current (XAML) WinUI 3 window.
95 | Microsoft.UI.Windowing.AppWindow appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
96 |
97 | // You now have an AppWindow object, and you can call its methods to manipulate the window.
98 | appWindow?.Resize(size);
99 | }
100 |
101 | protected override void OnNavigatedTo(NavigationEventArgs e)
102 | {
103 | base.OnNavigatedTo(e);
104 |
105 | // Retrieve the window handle (HWND) of the current (XAML) WinUI 3 window.
106 | nint hWnd = HwndExtensions.GetActiveWindow();
107 |
108 | // Retrieve the WindowId that corresponds to hWnd.
109 | Microsoft.UI.WindowId windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
110 |
111 | // Lastly, retrieve the AppWindow for the current (XAML) WinUI 3 window.
112 | Microsoft.UI.Windowing.AppWindow appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
113 |
114 | // You now have an AppWindow object, and you can call its methods to manipulate the window.
115 | if (appWindow == App.Window.GetAppWindow())
116 | {
117 | CompactUIGrid.Visibility = Visibility.Collapsed;
118 | ExtendedUIGrid.Visibility = Visibility.Visible;
119 | Keypad.Visibility = Visibility.Collapsed;
120 | }
121 | else
122 | {
123 | appWindow?.Resize(new SizeInt32 { Width = 400, Height = 100 });
124 | }
125 |
126 | if (SettingsManager.getProximitySensorOn())
127 | {
128 | App.Current.DeviceSystem.IsDisplayControlledByProximitySensor = true;
129 | }
130 | }
131 |
132 | protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
133 | {
134 | if (SettingsManager.getProximitySensorOn())
135 | {
136 | App.Current.DeviceSystem.IsDisplayControlledByProximitySensor = false;
137 | }
138 |
139 | base.OnNavigatingFrom(e);
140 | }
141 |
142 | private async void CloseCallButton_Click(object sender, RoutedEventArgs e)
143 | {
144 | try
145 | {
146 | CallManager.ActiveCall?.End();
147 | }
148 | catch (Exception ex)
149 | {
150 | _ = await new ContentDialog() { Title = "Unhandled Exception", Content = ex.ToString(), XamlRoot = XamlRoot, IsPrimaryButtonEnabled = true, PrimaryButtonText = "Ok" }.ShowAsync();
151 | }
152 | }
153 | private void HideExtendedUIButton_Click(object sender, RoutedEventArgs e)
154 | {
155 | ExtendedUIGrid.Visibility = Visibility.Collapsed;
156 | CompactUIGrid.Visibility = Visibility.Visible;
157 |
158 | ResizeView(new SizeInt32 { Width = 400, Height = 100 });
159 | }
160 |
161 | private void ShowExtendedUIButton_Click(object sender, RoutedEventArgs e)
162 | {
163 | CompactUIGrid.Visibility = Visibility.Collapsed;
164 | ExtendedUIGrid.Visibility = Visibility.Visible;
165 |
166 | if (KeypadToggleButton.IsChecked.GetValueOrDefault())
167 | {
168 | ResizeView(new SizeInt32 { Width = 400, Height = 730 });
169 | }
170 | else
171 | {
172 | ResizeView(new SizeInt32 { Width = 400, Height = 530 });
173 | }
174 | }
175 |
176 | private void KeypadToggleButton_Checked(object sender, RoutedEventArgs e)
177 | {
178 | Keypad.Visibility = Visibility.Visible;
179 |
180 | ResizeView(new SizeInt32 { Width = 400, Height = 730 });
181 | }
182 |
183 | private void KeypadToggleButton_Unchecked(object sender, RoutedEventArgs e)
184 | {
185 | Keypad.Visibility = Visibility.Collapsed;
186 |
187 | ResizeView(new SizeInt32 { Width = 400, Height = 530 });
188 | }
189 |
190 | private void Abtb_Hold_Unchecked(object sender, RoutedEventArgs e)
191 | {
192 | CallManager.ActiveCall?.SetHold(false);
193 | }
194 |
195 | private void Abtb_Hold_Checked(object sender, RoutedEventArgs e)
196 | {
197 | CallManager.ActiveCall?.SetHold(true);
198 | }
199 |
200 | private void SpeakerOutputButton_Checked(object sender, RoutedEventArgs e)
201 | {
202 | CallManager.AudioEndpoint = PhoneAudioRoutingEndpoint.Speakerphone;
203 | }
204 |
205 | private void SpeakerOutputButton_Unchecked(object sender, RoutedEventArgs e)
206 | {
207 | CallManager.AudioEndpoint = PhoneAudioRoutingEndpoint.Default;
208 | }
209 | }
210 | }
--------------------------------------------------------------------------------
/Dialer/Strings/it-IT/Resources.resw:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | Chiama
122 |
123 |
124 | Chiudi
125 |
126 |
127 |
128 |
129 |
130 | +
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 | ABC
143 |
144 |
145 |
146 |
147 |
148 | DEF
149 |
150 |
151 |
152 |
153 |
154 | GHI
155 |
156 |
157 |
158 |
159 |
160 | JKL
161 |
162 |
163 |
164 |
165 |
166 | MNO
167 |
168 |
169 |
170 |
171 |
172 | PQRS
173 |
174 |
175 |
176 |
177 |
178 | TUV
179 |
180 |
181 |
182 |
183 |
184 | WXYZ
185 |
186 |
187 |
188 | *
189 |
190 |
191 |
192 | *
193 |
194 |
195 |
196 | #
197 |
198 |
199 |
200 | #
201 |
202 |
--------------------------------------------------------------------------------
/Dialer/UI/Pages/DialPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using Dialer.Systems;
2 | using Microsoft.UI.Windowing;
3 | using Microsoft.UI.Xaml;
4 | using Microsoft.UI.Xaml.Controls;
5 | using Microsoft.UI.Xaml.Input;
6 | using Microsoft.UI.Xaml.Navigation;
7 | using System;
8 | using System.Collections.ObjectModel;
9 | using System.Linq;
10 | using System.Text;
11 | using Windows.ApplicationModel.Calls;
12 | using Windows.Globalization.PhoneNumberFormatting;
13 | using Windows.System;
14 | using WinUIEx;
15 |
16 | namespace Dialer.UI.Pages
17 | {
18 | public sealed partial class DialPage : Page
19 | {
20 | private CallSystem CallSystem => App.Current.CallSystem;
21 | private StringBuilder Number;
22 | private DisplayableLine CurrentPhoneLine;
23 |
24 | private ObservableCollection DisplayableLines => App.Current.CallSystem.DisplayableLines;
25 |
26 | private readonly AppWindow appWindow;
27 |
28 | public DialPage()
29 | {
30 | // Retrieve the window handle (HWND) of the current (XAML) WinUI 3 window.
31 | nint hWnd = HwndExtensions.GetActiveWindow();
32 |
33 | // Retrieve the WindowId that corresponds to hWnd.
34 | Microsoft.UI.WindowId windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
35 |
36 | // Lastly, retrieve the AppWindow for the current (XAML) WinUI 3 window.
37 | appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
38 |
39 | InitializeComponent();
40 | CallSystem.Lines.CollectionChanged += Lines_CollectionChanged;
41 |
42 | if (CallSystem.DefaultLine != null && DisplayableLines.Any(x => x.Line.Id == CallSystem.DefaultLine.Id))
43 | {
44 | CurrentPhoneLine = DisplayableLines.First(x => x.Line.Id == CallSystem.DefaultLine.Id);
45 | }
46 |
47 | PhoneLineSelector.SelectedItem = CurrentPhoneLine;
48 | }
49 |
50 | private void Lines_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
51 | {
52 | _ = App.Window.DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
53 | {
54 | switch (e.Action)
55 | {
56 | case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
57 | {
58 | bool SetAsDefault = DisplayableLines.Count == 0;
59 | DisplayableLine itemToAdd = new(e.NewItems[0] as PhoneLine);
60 | if (SetAsDefault)
61 | {
62 | CurrentPhoneLine = itemToAdd;
63 | }
64 |
65 | break;
66 | }
67 | case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
68 | {
69 | DisplayableLine itemToRemove = DisplayableLines.First(x => x.Line.Id == (e.OldItems[0] as PhoneLine)?.Id);
70 | if (CurrentPhoneLine == itemToRemove)
71 | {
72 | CurrentPhoneLine = DisplayableLines.Count > 0 ? DisplayableLines.First() : null;
73 | }
74 | break;
75 | }
76 | case System.Collections.Specialized.NotifyCollectionChangedAction.Replace:
77 | {
78 | DisplayableLine itemToReplace = DisplayableLines.First(x => x.Line.Id == (e.OldItems[0] as PhoneLine)?.Id);
79 | DisplayableLine itemToAdd = new(e.NewItems[0] as PhoneLine);
80 | if (CurrentPhoneLine == itemToReplace)
81 | {
82 | CurrentPhoneLine = itemToAdd;
83 | }
84 | break;
85 | }
86 | }
87 | });
88 | }
89 |
90 | private void DeleteLastNumberButton_Click(object sender, RoutedEventArgs e)
91 | {
92 | if (Number.Length > 0)
93 | {
94 | _ = Number.Remove(Number.Length - 1, 1);
95 | }
96 | UpdateCurrentNumber();
97 | }
98 |
99 | private void NumPad_DigitTapped(object sender, char e)
100 | {
101 | _ = Number.Append(e);
102 | UpdateCurrentNumber();
103 | }
104 |
105 | protected override void OnNavigatedTo(NavigationEventArgs e)
106 | {
107 | base.OnNavigatedTo(e);
108 | Number = e.Parameter switch
109 | {
110 | string number => new StringBuilder(number),
111 | _ => new StringBuilder(),
112 | };
113 | UpdateCurrentNumber();
114 | }
115 |
116 | private void UpdateCurrentNumber()
117 | {
118 | callButton.IsEnabled = !string.IsNullOrWhiteSpace(Number.ToString());
119 | PhoneNumberFormatter a = new();
120 | numberToDialBox.Text = a.FormatPartialString(Number.ToString());
121 | }
122 |
123 | private void CallButton_Click(object sender, RoutedEventArgs e)
124 | {
125 | try
126 | {
127 | CurrentPhoneLine?.Line?.DialWithOptions(new PhoneDialOptions() { Number = Number.ToString() });
128 | }
129 | catch (Exception ee)
130 | {
131 | handleException(ee);
132 | }
133 | }
134 |
135 | public async void handleException(Exception e)
136 | {
137 | _ = await new ContentDialog() { Title = "Unhandled Exception", Content = e.Message + "\n\n\n" + e.StackTrace, XamlRoot = XamlRoot, IsPrimaryButtonEnabled = true, PrimaryButtonText = "Ok" }.ShowAsync();
138 | }
139 |
140 | private void Page_KeyUp(object sender, KeyRoutedEventArgs e)
141 | {
142 | switch (e.Key)
143 | {
144 | case VirtualKey.Number0:
145 | case VirtualKey.NumberPad0:
146 | NumPad_DigitTapped(this, '0');
147 | break;
148 | case VirtualKey.Number1:
149 | case VirtualKey.NumberPad1:
150 | NumPad_DigitTapped(this, '1');
151 | break;
152 | case VirtualKey.Number2:
153 | case VirtualKey.NumberPad2:
154 | NumPad_DigitTapped(this, '2');
155 | break;
156 | case VirtualKey.Number3:
157 | case VirtualKey.NumberPad3:
158 | NumPad_DigitTapped(this, '3');
159 | break;
160 | case VirtualKey.Number4:
161 | case VirtualKey.NumberPad4:
162 | NumPad_DigitTapped(this, '4');
163 | break;
164 | case VirtualKey.Number5:
165 | case VirtualKey.NumberPad5:
166 | NumPad_DigitTapped(this, '5');
167 | break;
168 | case VirtualKey.Number6:
169 | case VirtualKey.NumberPad6:
170 | NumPad_DigitTapped(this, '6');
171 | break;
172 | case VirtualKey.Number7:
173 | case VirtualKey.NumberPad7:
174 | NumPad_DigitTapped(this, '7');
175 | break;
176 | case VirtualKey.Number8:
177 | case VirtualKey.NumberPad8:
178 | NumPad_DigitTapped(this, '8');
179 | break;
180 | case VirtualKey.Number9:
181 | case VirtualKey.NumberPad9:
182 | NumPad_DigitTapped(this, '9');
183 | break;
184 | case (VirtualKey)187:
185 | case VirtualKey.Add:
186 | NumPad_DigitTapped(this, '+');
187 | break;
188 | case VirtualKey.Back:
189 | DeleteLastNumberButton_Click(this, null);
190 | break;
191 | }
192 | }
193 |
194 | private void PhoneLineSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
195 | {
196 | if (e.AddedItems?.Count > 0 && e.AddedItems[0] != null)
197 | {
198 | CurrentPhoneLine = e.AddedItems[0] as DisplayableLine;
199 | }
200 | else if (DisplayableLines.Count > 0)
201 | {
202 | CurrentPhoneLine = DisplayableLines.First();
203 | }
204 | PhoneLineSelector.SelectedItem = CurrentPhoneLine;
205 | }
206 | }
207 | }
208 |
--------------------------------------------------------------------------------