Compare commits
1 Commits
dev
...
contact-mo
Author | SHA1 | Date | |
---|---|---|---|
89a70c44fe |
@ -1,38 +0,0 @@
|
|||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- website/**
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
runs-on: debian
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: website
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v1
|
|
||||||
- name: setup env
|
|
||||||
run: |
|
|
||||||
. ./.env || true
|
|
||||||
if [ "${{ gitea.ref_name }}" == prod ] && [ -n "$PROD_URL" ]; then
|
|
||||||
BASE_URL="$PROD_URL"
|
|
||||||
else
|
|
||||||
BASE_URL="${{ gitea.ref_name }}.$(tr / '\n' <<< "${{ gitea.repository }}" | tac | tr '\n' .)k8s.gmoker.com"
|
|
||||||
fi
|
|
||||||
REGISTRY="$(sed 's .*:// ' <<< ${{ gitea.server_url }})"
|
|
||||||
cat <<EOF >> .env
|
|
||||||
BASE_URL="$(printf '%s' "$BASE_URL" | tr '[:upper:]' '[:lower:]' | tr -c '[:lower:][:digit:]-.' -)"
|
|
||||||
IMAGEAPP="$REGISTRY/$(printf '%s' "${{ gitea.repository }}:${{ gitea.ref_name }}" | tr '[:upper:]' '[:lower:]' | tr -c '[:lower:][:digit:]-/:_' _)"
|
|
||||||
EOF
|
|
||||||
cat .env
|
|
||||||
|
|
||||||
- uses: actions/kaniko@v1
|
|
||||||
with:
|
|
||||||
password: "${{ secrets.PKGRW }}"
|
|
||||||
dockerfile: website/Dockerfile
|
|
||||||
|
|
||||||
- uses: actions/k8sdeploy@v1
|
|
||||||
with:
|
|
||||||
kubeconfig: "${{ secrets.K8S }}"
|
|
||||||
registry_password: "${{ secrets.PKGRW }}"
|
|
||||||
workdir: website
|
|
13
README.md
@ -1,13 +0,0 @@
|
|||||||
# Icing
|
|
||||||
|
|
||||||
An Epitech Innovation Project
|
|
||||||
|
|
||||||
*By*
|
|
||||||
**Bartosz Michalak - Alexis Danlos - Florian Griffon - Ange Duhayon - Stéphane Corbière**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
The **docs** folder contains documentation about:
|
|
||||||
- The project
|
|
||||||
- A user manual
|
|
||||||
- Our automations
|
|
5
dialer/README.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# ICING Dialer
|
||||||
|
|
||||||
|
Project aiming to <i>ice</i> your **non-internet** phone calls, thanks to a custom and super-cryptographic dialer app.
|
||||||
|
|
||||||
|
Like & Follow !
|
1
dialer/android/.gitignore
vendored
@ -5,7 +5,6 @@ gradle-wrapper.jar
|
|||||||
/gradlew.bat
|
/gradlew.bat
|
||||||
/local.properties
|
/local.properties
|
||||||
GeneratedPluginRegistrant.java
|
GeneratedPluginRegistrant.java
|
||||||
gradle.properties
|
|
||||||
|
|
||||||
# Remember to never publicly share your keystore.
|
# Remember to never publicly share your keystore.
|
||||||
# See https://flutter.dev/to/reference-keystore
|
# See https://flutter.dev/to/reference-keystore
|
||||||
|
@ -2,3 +2,5 @@ org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryErro
|
|||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
dev.steenbakker.mobile_scanner.useUnbundled=true
|
dev.steenbakker.mobile_scanner.useUnbundled=true
|
||||||
|
org.gradle.java.home=/usr/lib/jvm/java-17-openjdk-amd64
|
||||||
|
#org.gradle.java.home=/usr/lib/jvm/java-17-openjdk-17.0.13.0.11-3.fc41.x86_64
|
||||||
|
34
dialer/ios/.gitignore
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
**/dgph
|
||||||
|
*.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
*.moved-aside
|
||||||
|
*.pbxuser
|
||||||
|
*.perspectivev3
|
||||||
|
**/*sync/
|
||||||
|
.sconsign.dblite
|
||||||
|
.tags*
|
||||||
|
**/.vagrant/
|
||||||
|
**/DerivedData/
|
||||||
|
Icon?
|
||||||
|
**/Pods/
|
||||||
|
**/.symlinks/
|
||||||
|
profile
|
||||||
|
xcuserdata
|
||||||
|
**/.generated/
|
||||||
|
Flutter/App.framework
|
||||||
|
Flutter/Flutter.framework
|
||||||
|
Flutter/Flutter.podspec
|
||||||
|
Flutter/Generated.xcconfig
|
||||||
|
Flutter/ephemeral/
|
||||||
|
Flutter/app.flx
|
||||||
|
Flutter/app.zip
|
||||||
|
Flutter/flutter_assets/
|
||||||
|
Flutter/flutter_export_environment.sh
|
||||||
|
ServiceDefinitions.json
|
||||||
|
Runner/GeneratedPluginRegistrant.*
|
||||||
|
|
||||||
|
# Exceptions to above rules.
|
||||||
|
!default.mode1v3
|
||||||
|
!default.mode2v3
|
||||||
|
!default.pbxuser
|
||||||
|
!default.perspectivev3
|
26
dialer/ios/Flutter/AppFrameworkInfo.plist
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>App</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>io.flutter.flutter.app</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>App</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>FMWK</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>MinimumOSVersion</key>
|
||||||
|
<string>12.0</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
1
dialer/ios/Flutter/Debug.xcconfig
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "Generated.xcconfig"
|
1
dialer/ios/Flutter/Release.xcconfig
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "Generated.xcconfig"
|
616
dialer/ios/Runner.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,616 @@
|
|||||||
|
// !$*UTF8*$!
|
||||||
|
{
|
||||||
|
archiveVersion = 1;
|
||||||
|
classes = {
|
||||||
|
};
|
||||||
|
objectVersion = 54;
|
||||||
|
objects = {
|
||||||
|
|
||||||
|
/* Begin PBXBuildFile section */
|
||||||
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||||
|
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||||
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||||
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||||
|
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||||
|
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||||
|
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||||
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
|
||||||
|
remoteInfo = Runner;
|
||||||
|
};
|
||||||
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = "";
|
||||||
|
dstSubfolderSpec = 10;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
name = "Embed Frameworks";
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXFileReference section */
|
||||||
|
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||||
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||||
|
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||||
|
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||||
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||||
|
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||||
|
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||||
|
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||||
|
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
|
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
|
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXGroup section */
|
||||||
|
331C8082294A63A400263BE5 /* RunnerTests */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
331C807B294A618700263BE5 /* RunnerTests.swift */,
|
||||||
|
);
|
||||||
|
path = RunnerTests;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
||||||
|
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||||
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||||
|
9740EEB31CF90195004384FC /* Generated.xcconfig */,
|
||||||
|
);
|
||||||
|
name = Flutter;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
97C146E51CF9000F007C117D = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
9740EEB11CF90186004384FC /* Flutter */,
|
||||||
|
97C146F01CF9000F007C117D /* Runner */,
|
||||||
|
97C146EF1CF9000F007C117D /* Products */,
|
||||||
|
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||||
|
);
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
97C146EF1CF9000F007C117D /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||||
|
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
97C146F01CF9000F007C117D /* Runner */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||||
|
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||||
|
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
||||||
|
97C147021CF9000F007C117D /* Info.plist */,
|
||||||
|
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
|
||||||
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
|
||||||
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
|
||||||
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
|
||||||
|
);
|
||||||
|
path = Runner;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXNativeTarget section */
|
||||||
|
331C8080294A63A400263BE5 /* RunnerTests */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
||||||
|
buildPhases = (
|
||||||
|
331C807D294A63A400263BE5 /* Sources */,
|
||||||
|
331C807F294A63A400263BE5 /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
331C8086294A63A400263BE5 /* PBXTargetDependency */,
|
||||||
|
);
|
||||||
|
name = RunnerTests;
|
||||||
|
productName = RunnerTests;
|
||||||
|
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
|
||||||
|
productType = "com.apple.product-type.bundle.unit-test";
|
||||||
|
};
|
||||||
|
97C146ED1CF9000F007C117D /* Runner */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||||
|
buildPhases = (
|
||||||
|
9740EEB61CF901F6004384FC /* Run Script */,
|
||||||
|
97C146EA1CF9000F007C117D /* Sources */,
|
||||||
|
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||||
|
97C146EC1CF9000F007C117D /* Resources */,
|
||||||
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = Runner;
|
||||||
|
productName = Runner;
|
||||||
|
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
|
||||||
|
productType = "com.apple.product-type.application";
|
||||||
|
};
|
||||||
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
|
/* Begin PBXProject section */
|
||||||
|
97C146E61CF9000F007C117D /* Project object */ = {
|
||||||
|
isa = PBXProject;
|
||||||
|
attributes = {
|
||||||
|
BuildIndependentTargetsInParallel = YES;
|
||||||
|
LastUpgradeCheck = 1510;
|
||||||
|
ORGANIZATIONNAME = "";
|
||||||
|
TargetAttributes = {
|
||||||
|
331C8080294A63A400263BE5 = {
|
||||||
|
CreatedOnToolsVersion = 14.0;
|
||||||
|
TestTargetID = 97C146ED1CF9000F007C117D;
|
||||||
|
};
|
||||||
|
97C146ED1CF9000F007C117D = {
|
||||||
|
CreatedOnToolsVersion = 7.3.1;
|
||||||
|
LastSwiftMigration = 1100;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
||||||
|
compatibilityVersion = "Xcode 9.3";
|
||||||
|
developmentRegion = en;
|
||||||
|
hasScannedForEncodings = 0;
|
||||||
|
knownRegions = (
|
||||||
|
en,
|
||||||
|
Base,
|
||||||
|
);
|
||||||
|
mainGroup = 97C146E51CF9000F007C117D;
|
||||||
|
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
|
||||||
|
projectDirPath = "";
|
||||||
|
projectRoot = "";
|
||||||
|
targets = (
|
||||||
|
97C146ED1CF9000F007C117D /* Runner */,
|
||||||
|
331C8080294A63A400263BE5 /* RunnerTests */,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
/* End PBXProject section */
|
||||||
|
|
||||||
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
331C807F294A63A400263BE5 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
97C146EC1CF9000F007C117D /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
||||||
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||||
|
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
||||||
|
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
alwaysOutOfDate = 1;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
|
||||||
|
);
|
||||||
|
name = "Thin Binary";
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
||||||
|
};
|
||||||
|
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
alwaysOutOfDate = 1;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "Run Script";
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||||
|
};
|
||||||
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
331C807D294A63A400263BE5 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
97C146EA1CF9000F007C117D /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
||||||
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXTargetDependency section */
|
||||||
|
331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = 97C146ED1CF9000F007C117D /* Runner */;
|
||||||
|
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
|
/* Begin PBXVariantGroup section */
|
||||||
|
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
97C146FB1CF9000F007C117D /* Base */,
|
||||||
|
);
|
||||||
|
name = Main.storyboard;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
97C147001CF9000F007C117D /* Base */,
|
||||||
|
);
|
||||||
|
name = LaunchScreen.storyboard;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXVariantGroup section */
|
||||||
|
|
||||||
|
/* Begin XCBuildConfiguration section */
|
||||||
|
249021D3217E4FDB00AE95B9 /* Profile */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
|
249021D4217E4FDB00AE95B9 /* Profile */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
ENABLE_BITCODE = NO;
|
||||||
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.example.dialer;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
|
331C8088294A63A400263BE5 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.example.dialer.RunnerTests;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
331C8089294A63A400263BE5 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.example.dialer.RunnerTests;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
331C808A294A63A400263BE5 /* Profile */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.example.dialer.RunnerTests;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
|
97C147031CF9000F007C117D /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_TESTABILITY = YES;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
|
"DEBUG=1",
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
97C147041CF9000F007C117D /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
97C147061CF9000F007C117D /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
ENABLE_BITCODE = NO;
|
||||||
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.example.dialer;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
97C147071CF9000F007C117D /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
ENABLE_BITCODE = NO;
|
||||||
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.example.dialer;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
|
/* Begin XCConfigurationList section */
|
||||||
|
331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
331C8088294A63A400263BE5 /* Debug */,
|
||||||
|
331C8089294A63A400263BE5 /* Release */,
|
||||||
|
331C808A294A63A400263BE5 /* Profile */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
97C147031CF9000F007C117D /* Debug */,
|
||||||
|
97C147041CF9000F007C117D /* Release */,
|
||||||
|
249021D3217E4FDB00AE95B9 /* Profile */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
97C147061CF9000F007C117D /* Debug */,
|
||||||
|
97C147071CF9000F007C117D /* Release */,
|
||||||
|
249021D4217E4FDB00AE95B9 /* Profile */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
/* End XCConfigurationList section */
|
||||||
|
};
|
||||||
|
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
||||||
|
}
|
7
dialer/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "self:">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>PreviewsEnabled</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@ -0,0 +1,98 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1510"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||||
|
BuildableName = "Runner.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||||
|
BuildableName = "Runner.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
<Testables>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO"
|
||||||
|
parallelizable = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "331C8080294A63A400263BE5"
|
||||||
|
BuildableName = "RunnerTests.xctest"
|
||||||
|
BlueprintName = "RunnerTests"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||||
|
BuildableName = "Runner.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Profile"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||||
|
BuildableName = "Runner.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>PreviewsEnabled</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
13
dialer/ios/Runner/AppDelegate.swift
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import Flutter
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
@main
|
||||||
|
@objc class AppDelegate: FlutterAppDelegate {
|
||||||
|
override func application(
|
||||||
|
_ application: UIApplication,
|
||||||
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||||
|
) -> Bool {
|
||||||
|
GeneratedPluginRegistrant.register(with: self)
|
||||||
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,122 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"size" : "20x20",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-20x20@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "20x20",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-20x20@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-29x29@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-29x29@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-29x29@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-40x40@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-40x40@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "60x60",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-60x60@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "60x60",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-60x60@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "20x20",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-20x20@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "20x20",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-20x20@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-29x29@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-29x29@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-40x40@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-40x40@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "76x76",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-76x76@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "76x76",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-76x76@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "83.5x83.5",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-83.5x83.5@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "1024x1024",
|
||||||
|
"idiom" : "ios-marketing",
|
||||||
|
"filename" : "Icon-App-1024x1024@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 295 B |
After Width: | Height: | Size: 406 B |
After Width: | Height: | Size: 450 B |
After Width: | Height: | Size: 282 B |
After Width: | Height: | Size: 462 B |
After Width: | Height: | Size: 704 B |
After Width: | Height: | Size: 406 B |
After Width: | Height: | Size: 586 B |
After Width: | Height: | Size: 862 B |
After Width: | Height: | Size: 862 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 762 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.4 KiB |
23
dialer/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "LaunchImage.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "LaunchImage@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "LaunchImage@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
BIN
dialer/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
vendored
Normal file
After Width: | Height: | Size: 68 B |
BIN
dialer/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
vendored
Normal file
After Width: | Height: | Size: 68 B |
BIN
dialer/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
vendored
Normal file
After Width: | Height: | Size: 68 B |
5
dialer/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Launch Screen Assets
|
||||||
|
|
||||||
|
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
|
||||||
|
|
||||||
|
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
|
37
dialer/ios/Runner/Base.lproj/LaunchScreen.storyboard
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||||
|
<dependencies>
|
||||||
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--View Controller-->
|
||||||
|
<scene sceneID="EHf-IW-A2E">
|
||||||
|
<objects>
|
||||||
|
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||||
|
<layoutGuides>
|
||||||
|
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
|
||||||
|
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
|
||||||
|
</layoutGuides>
|
||||||
|
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
|
||||||
|
</imageView>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
|
||||||
|
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
|
||||||
|
</constraints>
|
||||||
|
</view>
|
||||||
|
</viewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="53" y="375"/>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
<resources>
|
||||||
|
<image name="LaunchImage" width="168" height="185"/>
|
||||||
|
</resources>
|
||||||
|
</document>
|
26
dialer/ios/Runner/Base.lproj/Main.storyboard
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
|
||||||
|
<dependencies>
|
||||||
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--Flutter View Controller-->
|
||||||
|
<scene sceneID="tne-QT-ifu">
|
||||||
|
<objects>
|
||||||
|
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
|
||||||
|
<layoutGuides>
|
||||||
|
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
||||||
|
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
||||||
|
</layoutGuides>
|
||||||
|
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||||
|
</view>
|
||||||
|
</viewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
</document>
|
52
dialer/ios/Runner/Info.plist
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>Dialer</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>dialer</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||||
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
<true/>
|
||||||
|
<key>UILaunchStoryboardName</key>
|
||||||
|
<string>LaunchScreen</string>
|
||||||
|
<key>UIMainStoryboardFile</key>
|
||||||
|
<string>Main</string>
|
||||||
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
|
<true/>
|
||||||
|
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||||
|
<true/>
|
||||||
|
<key>NSContactsUsageDescription</key>
|
||||||
|
<string>Contacts for calls/string>
|
||||||
|
|
||||||
|
</dict>
|
||||||
|
</plist>
|
1
dialer/ios/Runner/Runner-Bridging-Header.h
Normal file
@ -0,0 +1 @@
|
|||||||
|
#import "GeneratedPluginRegistrant.h"
|
12
dialer/ios/RunnerTests/RunnerTests.swift
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import Flutter
|
||||||
|
import UIKit
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
class RunnerTests: XCTestCase {
|
||||||
|
|
||||||
|
func testExample() {
|
||||||
|
// If you add code to the Runner application, consider adding tests here.
|
||||||
|
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -94,46 +94,6 @@ class _ContactModalState extends State<ContactModal> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _deleteContact() async {
|
|
||||||
final bool shouldDelete = await showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) => AlertDialog(
|
|
||||||
title: const Text('Delete Contact'),
|
|
||||||
content: Text('Are you sure you want to delete ${widget.contact.displayName}?'),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => Navigator.of(context).pop(false),
|
|
||||||
child: const Text('Cancel'),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => Navigator.of(context).pop(true),
|
|
||||||
child: const Text('Delete'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (shouldDelete) {
|
|
||||||
try {
|
|
||||||
// Delete the contact
|
|
||||||
await FlutterContacts.deleteContact(widget.contact);
|
|
||||||
|
|
||||||
// Show success message
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(content: Text('${widget.contact.displayName} deleted')),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Close the modal
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
} catch (e) {
|
|
||||||
// Handle errors and show a failure message
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(content: Text('Failed to delete ${widget.contact.displayName}: $e')),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
String email = widget.contact.emails.isNotEmpty
|
String email = widget.contact.emails.isNotEmpty
|
||||||
@ -181,9 +141,8 @@ void _deleteContact() async {
|
|||||||
icon: const Icon(Icons.more_vert,
|
icon: const Icon(Icons.more_vert,
|
||||||
color: Colors.white),
|
color: Colors.white),
|
||||||
onSelected: (String choice) {
|
onSelected: (String choice) {
|
||||||
if (choice == 'delete') {
|
// Implement actions here
|
||||||
_deleteContact();
|
debugPrint('Selected: $choice');
|
||||||
}
|
|
||||||
},
|
},
|
||||||
itemBuilder: (BuildContext context) {
|
itemBuilder: (BuildContext context) {
|
||||||
return [
|
return [
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
|
// history_page.dart
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_contacts/flutter_contacts.dart';
|
import 'package:flutter_contacts/flutter_contacts.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart'; // For date formatting
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
import 'package:dialer/features/contacts/contact_state.dart';
|
import 'package:dialer/features/contacts/contact_state.dart';
|
||||||
import 'package:dialer/widgets/username_color_generator.dart';
|
|
||||||
import 'package:dialer/widgets/color_darkener.dart';
|
|
||||||
|
|
||||||
class History {
|
class History {
|
||||||
final Contact contact;
|
final Contact contact;
|
||||||
@ -29,10 +28,9 @@ class HistoryPage extends StatefulWidget {
|
|||||||
_HistoryPageState createState() => _HistoryPageState();
|
_HistoryPageState createState() => _HistoryPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _HistoryPageState extends State<HistoryPage> with SingleTickerProviderStateMixin {
|
class _HistoryPageState extends State<HistoryPage> {
|
||||||
List<History> histories = [];
|
List<History> histories = [];
|
||||||
bool loading = true;
|
bool loading = true;
|
||||||
int? _expandedIndex;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
@ -53,6 +51,7 @@ class _HistoryPageState extends State<HistoryPage> with SingleTickerProviderStat
|
|||||||
}
|
}
|
||||||
List<Contact> contacts = contactState.contacts;
|
List<Contact> contacts = contactState.contacts;
|
||||||
|
|
||||||
|
// Ensure there are enough contacts
|
||||||
if (contacts.isEmpty) {
|
if (contacts.isEmpty) {
|
||||||
setState(() {
|
setState(() {
|
||||||
loading = false;
|
loading = false;
|
||||||
@ -60,6 +59,7 @@ class _HistoryPageState extends State<HistoryPage> with SingleTickerProviderStat
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build histories using the contacts
|
||||||
setState(() {
|
setState(() {
|
||||||
histories = List.generate(
|
histories = List.generate(
|
||||||
contacts.length >= 10 ? 10 : contacts.length,
|
contacts.length >= 10 ? 10 : contacts.length,
|
||||||
@ -75,47 +75,6 @@ class _HistoryPageState extends State<HistoryPage> with SingleTickerProviderStat
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
List _buildGroupedList(List<History> historyList) {
|
|
||||||
// Sort histories by date (most recent first)
|
|
||||||
historyList.sort((a, b) => b.date.compareTo(a.date));
|
|
||||||
|
|
||||||
final now = DateTime.now();
|
|
||||||
final today = DateTime(now.year, now.month, now.day);
|
|
||||||
final yesterday = today.subtract(const Duration(days: 1));
|
|
||||||
|
|
||||||
List<History> todayHistories = [];
|
|
||||||
List<History> yesterdayHistories = [];
|
|
||||||
List<History> olderHistories = [];
|
|
||||||
|
|
||||||
for (var history in historyList) {
|
|
||||||
final callDate = DateTime(history.date.year, history.date.month, history.date.day);
|
|
||||||
if (callDate == today) {
|
|
||||||
todayHistories.add(history);
|
|
||||||
} else if (callDate == yesterday) {
|
|
||||||
yesterdayHistories.add(history);
|
|
||||||
} else {
|
|
||||||
olderHistories.add(history);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Combine them with headers
|
|
||||||
final items = <dynamic>[];
|
|
||||||
if (todayHistories.isNotEmpty) {
|
|
||||||
items.add('Today');
|
|
||||||
items.addAll(todayHistories);
|
|
||||||
}
|
|
||||||
if (yesterdayHistories.isNotEmpty) {
|
|
||||||
items.add('Yesterday');
|
|
||||||
items.addAll(yesterdayHistories);
|
|
||||||
}
|
|
||||||
if (olderHistories.isNotEmpty) {
|
|
||||||
items.add('Older');
|
|
||||||
items.addAll(olderHistories);
|
|
||||||
}
|
|
||||||
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final contactState = ContactState.of(context);
|
final contactState = ContactState.of(context);
|
||||||
@ -123,6 +82,9 @@ class _HistoryPageState extends State<HistoryPage> with SingleTickerProviderStat
|
|||||||
if (loading || contactState.loading) {
|
if (loading || contactState.loading) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('History'),
|
||||||
|
),
|
||||||
body: const Center(
|
body: const Center(
|
||||||
child: CircularProgressIndicator(),
|
child: CircularProgressIndicator(),
|
||||||
),
|
),
|
||||||
@ -132,6 +94,9 @@ class _HistoryPageState extends State<HistoryPage> with SingleTickerProviderStat
|
|||||||
if (histories.isEmpty) {
|
if (histories.isEmpty) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('History'),
|
||||||
|
),
|
||||||
body: const Center(
|
body: const Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'No call history available.',
|
'No call history available.',
|
||||||
@ -141,82 +106,27 @@ class _HistoryPageState extends State<HistoryPage> with SingleTickerProviderStat
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter missed calls
|
return Scaffold(
|
||||||
List<History> missedCalls = histories.where((h) => h.callStatus == 'missed').toList();
|
|
||||||
|
|
||||||
final allItems = _buildGroupedList(histories);
|
|
||||||
final missedItems = _buildGroupedList(missedCalls);
|
|
||||||
|
|
||||||
return DefaultTabController(
|
|
||||||
length: 2,
|
|
||||||
child: Scaffold(
|
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
appBar: PreferredSize(
|
appBar: AppBar(
|
||||||
preferredSize: const Size.fromHeight(kToolbarHeight),
|
title: const Text('History'),
|
||||||
child: Container(
|
|
||||||
color: Colors.black,
|
|
||||||
child: const TabBar(
|
|
||||||
tabs: [
|
|
||||||
Tab(text: 'All Calls'),
|
|
||||||
Tab(text: 'Missed Calls'),
|
|
||||||
],
|
|
||||||
indicatorColor: Colors.white,
|
|
||||||
),
|
),
|
||||||
),
|
body: ListView.builder(
|
||||||
),
|
itemCount: histories.length,
|
||||||
body: TabBarView(
|
|
||||||
children: [
|
|
||||||
// All Calls
|
|
||||||
_buildListView(allItems),
|
|
||||||
// Missed Calls
|
|
||||||
_buildListView(missedItems),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildListView(List items) {
|
|
||||||
return ListView.builder(
|
|
||||||
itemCount: items.length,
|
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final item = items[index];
|
final history = histories[index];
|
||||||
|
|
||||||
if (item is String) {
|
|
||||||
// This is a header item
|
|
||||||
return Container(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
|
||||||
color: Colors.grey[900],
|
|
||||||
child: Text(
|
|
||||||
item,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.white70,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else if (item is History) {
|
|
||||||
final history = item;
|
|
||||||
final contact = history.contact;
|
final contact = history.contact;
|
||||||
final isExpanded = _expandedIndex == index;
|
|
||||||
|
|
||||||
// Generate the avatar color
|
return ListTile(
|
||||||
Color avatarColor = generateColorFromName(contact.displayName);
|
|
||||||
|
|
||||||
return Column(
|
|
||||||
children: [
|
|
||||||
ListTile(
|
|
||||||
leading: (contact.thumbnail != null && contact.thumbnail!.isNotEmpty)
|
leading: (contact.thumbnail != null && contact.thumbnail!.isNotEmpty)
|
||||||
? CircleAvatar(
|
? CircleAvatar(
|
||||||
backgroundImage: MemoryImage(contact.thumbnail!),
|
backgroundImage: MemoryImage(contact.thumbnail!),
|
||||||
)
|
)
|
||||||
: CircleAvatar(
|
: CircleAvatar(
|
||||||
backgroundColor: avatarColor,
|
|
||||||
child: Text(
|
child: Text(
|
||||||
contact.displayName.isNotEmpty
|
contact.displayName.isNotEmpty
|
||||||
? contact.displayName[0].toUpperCase()
|
? contact.displayName[0]
|
||||||
: '?',
|
: '?',
|
||||||
style: TextStyle(color: darken(avatarColor, 0.4)),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
@ -227,212 +137,15 @@ class _HistoryPageState extends State<HistoryPage> with SingleTickerProviderStat
|
|||||||
'${history.callType} - ${history.callStatus} - ${DateFormat('MMM dd, hh:mm a').format(history.date)}',
|
'${history.callType} - ${history.callStatus} - ${DateFormat('MMM dd, hh:mm a').format(history.date)}',
|
||||||
style: const TextStyle(color: Colors.grey),
|
style: const TextStyle(color: Colors.grey),
|
||||||
),
|
),
|
||||||
trailing: Row(
|
trailing: Text(
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'${history.attempts}x',
|
'${history.attempts}x',
|
||||||
style: const TextStyle(color: Colors.white),
|
style: const TextStyle(color: Colors.white),
|
||||||
),
|
),
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.phone, color: Colors.green),
|
|
||||||
onPressed: () async {
|
|
||||||
if (contact.phones.isNotEmpty) {
|
|
||||||
final Uri callUri =
|
|
||||||
Uri(scheme: 'tel', path: contact.phones.first.number);
|
|
||||||
if (await canLaunchUrl(callUri)) {
|
|
||||||
await launchUrl(callUri);
|
|
||||||
} else {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(content: Text('Could not launch call')),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(content: Text('Contact has no phone number')),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
// Handle tap event if needed
|
||||||
_expandedIndex = isExpanded ? null : index;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
if (isExpanded)
|
|
||||||
Container(
|
|
||||||
color: Colors.grey[850],
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
|
||||||
TextButton.icon(
|
|
||||||
onPressed: () async {
|
|
||||||
if (history.contact.phones.isNotEmpty) {
|
|
||||||
final Uri smsUri =
|
|
||||||
Uri(scheme: 'sms', path: history.contact.phones.first.number);
|
|
||||||
if (await canLaunchUrl(smsUri)) {
|
|
||||||
await launchUrl(smsUri);
|
|
||||||
} else {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(content: Text('Could not send message')),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(content: Text('Contact has no phone number')),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
icon: const Icon(Icons.message, color: Colors.white),
|
|
||||||
label: const Text('Message', style: TextStyle(color: Colors.white)),
|
|
||||||
),
|
|
||||||
TextButton.icon(
|
|
||||||
onPressed: () {
|
|
||||||
// Navigate to Call Details page
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (_) => CallDetailsPage(history: history),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
icon: const Icon(Icons.info, color: Colors.white),
|
|
||||||
label: const Text('Details', style: TextStyle(color: Colors.white)),
|
|
||||||
),
|
|
||||||
TextButton.icon(
|
|
||||||
onPressed: () {
|
|
||||||
// Implement block number functionality
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(
|
|
||||||
content: Text('Number blocked (functionality not implemented)'),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
icon: const Icon(Icons.block, color: Colors.white),
|
|
||||||
label: const Text('Block', style: TextStyle(color: Colors.white)),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
}
|
|
||||||
|
|
||||||
class CallDetailsPage extends StatelessWidget {
|
|
||||||
final History history;
|
|
||||||
|
|
||||||
const CallDetailsPage({Key? key, required this.history}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final contact = history.contact;
|
|
||||||
|
|
||||||
return Scaffold(
|
|
||||||
backgroundColor: Colors.black,
|
|
||||||
appBar: AppBar(
|
|
||||||
title: const Text('Call Details'),
|
|
||||||
backgroundColor: Colors.black,
|
|
||||||
),
|
|
||||||
body: Padding(
|
|
||||||
padding: const EdgeInsets.all(16.0),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
// Display Contact Name and Thumbnail
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
(contact.thumbnail != null && contact.thumbnail!.isNotEmpty)
|
|
||||||
? CircleAvatar(
|
|
||||||
backgroundImage: MemoryImage(contact.thumbnail!),
|
|
||||||
radius: 30,
|
|
||||||
)
|
|
||||||
: CircleAvatar(
|
|
||||||
backgroundColor: Colors.grey[700],
|
|
||||||
radius: 30,
|
|
||||||
child: Text(
|
|
||||||
contact.displayName.isNotEmpty
|
|
||||||
? contact.displayName[0].toUpperCase()
|
|
||||||
: '?',
|
|
||||||
style: const TextStyle(color: Colors.white),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 16),
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
contact.displayName,
|
|
||||||
style: const TextStyle(color: Colors.white, fontSize: 24),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 24),
|
|
||||||
|
|
||||||
// Display call type, status, date, attempts
|
|
||||||
DetailRow(
|
|
||||||
label: 'Call Type:',
|
|
||||||
value: history.callType,
|
|
||||||
),
|
|
||||||
DetailRow(
|
|
||||||
label: 'Call Status:',
|
|
||||||
value: history.callStatus,
|
|
||||||
),
|
|
||||||
DetailRow(
|
|
||||||
label: 'Date:',
|
|
||||||
value: DateFormat('MMM dd, yyyy - hh:mm a').format(history.date),
|
|
||||||
),
|
|
||||||
DetailRow(
|
|
||||||
label: 'Attempts:',
|
|
||||||
value: '${history.attempts}',
|
|
||||||
),
|
|
||||||
|
|
||||||
const SizedBox(height: 24),
|
|
||||||
|
|
||||||
// If you have more details like duration, contact number, etc.
|
|
||||||
if (contact.phones.isNotEmpty)
|
|
||||||
DetailRow(
|
|
||||||
label: 'Number:',
|
|
||||||
value: contact.phones.first.number,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DetailRow extends StatelessWidget {
|
|
||||||
final String label;
|
|
||||||
final String value;
|
|
||||||
|
|
||||||
const DetailRow({Key? key, required this.label, required this.value}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
label,
|
|
||||||
style: const TextStyle(color: Colors.white70, fontWeight: FontWeight.bold),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
value,
|
|
||||||
style: const TextStyle(color: Colors.white),
|
|
||||||
textAlign: TextAlign.right,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,7 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
// Set the TabController length to 3
|
_tabController = TabController(length: 4, vsync: this, initialIndex: 1);
|
||||||
_tabController = TabController(length: 3, vsync: this, initialIndex: 1);
|
|
||||||
_tabController.addListener(_handleTabIndex);
|
_tabController.addListener(_handleTabIndex);
|
||||||
_fetchContacts();
|
_fetchContacts();
|
||||||
}
|
}
|
||||||
@ -70,9 +69,6 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
left: 16.0,
|
left: 16.0,
|
||||||
right: 16.0,
|
right: 16.0,
|
||||||
),
|
),
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color.fromARGB(255, 30, 30, 30),
|
color: const Color.fromARGB(255, 30, 30, 30),
|
||||||
@ -81,17 +77,14 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
top: BorderSide(color: Colors.grey.shade800, width: 1),
|
top: BorderSide(color: Colors.grey.shade800, width: 1),
|
||||||
left: BorderSide(color: Colors.grey.shade800, width: 1),
|
left: BorderSide(color: Colors.grey.shade800, width: 1),
|
||||||
right: BorderSide(color: Colors.grey.shade800, width: 1),
|
right: BorderSide(color: Colors.grey.shade800, width: 1),
|
||||||
bottom:
|
bottom: BorderSide(color: Colors.grey.shade800, width: 2),
|
||||||
BorderSide(color: Colors.grey.shade800, width: 2),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: SearchAnchor(
|
child: SearchAnchor(
|
||||||
builder:
|
builder: (BuildContext context, SearchController controller) {
|
||||||
(BuildContext context, SearchController controller) {
|
|
||||||
return SearchBar(
|
return SearchBar(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
padding:
|
padding: WidgetStateProperty.all<EdgeInsetsGeometry>(
|
||||||
MaterialStateProperty.all<EdgeInsetsGeometry>(
|
|
||||||
const EdgeInsets.only(
|
const EdgeInsets.only(
|
||||||
top: 6.0,
|
top: 6.0,
|
||||||
bottom: 6.0,
|
bottom: 6.0,
|
||||||
@ -103,10 +96,10 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
controller.openView();
|
controller.openView();
|
||||||
_onSearchChanged('');
|
_onSearchChanged('');
|
||||||
},
|
},
|
||||||
backgroundColor: MaterialStateProperty.all(
|
backgroundColor: WidgetStateProperty.all(
|
||||||
const Color.fromARGB(255, 30, 30, 30)),
|
const Color.fromARGB(255, 30, 30, 30)),
|
||||||
hintText: 'Search contacts',
|
hintText: 'Search contacts',
|
||||||
hintStyle: MaterialStateProperty.all(
|
hintStyle: WidgetStateProperty.all(
|
||||||
const TextStyle(color: Colors.grey, fontSize: 16.0),
|
const TextStyle(color: Colors.grey, fontSize: 16.0),
|
||||||
),
|
),
|
||||||
leading: const Icon(
|
leading: const Icon(
|
||||||
@ -114,8 +107,7 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
size: 24.0,
|
size: 24.0,
|
||||||
),
|
),
|
||||||
shape:
|
shape: WidgetStateProperty.all<RoundedRectangleBorder>(
|
||||||
MaterialStateProperty.all<RoundedRectangleBorder>(
|
|
||||||
RoundedRectangleBorder(
|
RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(12.0),
|
borderRadius: BorderRadius.circular(12.0),
|
||||||
),
|
),
|
||||||
@ -141,28 +133,6 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// 3-dot menu
|
|
||||||
PopupMenuButton<String>(
|
|
||||||
icon: const Icon(Icons.more_vert, color: Colors.white),
|
|
||||||
itemBuilder: (BuildContext context) => [
|
|
||||||
const PopupMenuItem<String>(
|
|
||||||
value: 'settings',
|
|
||||||
child: Text('Settings'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
onSelected: (String value) {
|
|
||||||
if (value == 'settings') {
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const SettingsPage()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// Main content with TabBarView
|
// Main content with TabBarView
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Stack(
|
child: Stack(
|
||||||
@ -173,6 +143,7 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
FavoritesPage(),
|
FavoritesPage(),
|
||||||
HistoryPage(),
|
HistoryPage(),
|
||||||
ContactPage(),
|
ContactPage(),
|
||||||
|
SettingsPage(), // Add your SettingsPage here
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
@ -216,6 +187,10 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
icon: Icon(_tabController.index == 2
|
icon: Icon(_tabController.index == 2
|
||||||
? Icons.contacts
|
? Icons.contacts
|
||||||
: Icons.contacts_outlined)),
|
: Icons.contacts_outlined)),
|
||||||
|
Tab(
|
||||||
|
icon: Icon(_tabController.index == 3 // Corrected index
|
||||||
|
? Icons.settings
|
||||||
|
: Icons.settings_outlined)),
|
||||||
],
|
],
|
||||||
labelColor: Colors.white,
|
labelColor: Colors.white,
|
||||||
unselectedLabelColor: const Color.fromARGB(255, 158, 158, 158),
|
unselectedLabelColor: const Color.fromARGB(255, 158, 158, 158),
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'key_storage.dart';
|
|
||||||
|
|
||||||
class DeleteKeyPairPage extends StatelessWidget {
|
class DeleteKeyPairPage extends StatelessWidget {
|
||||||
const DeleteKeyPairPage({super.key});
|
const DeleteKeyPairPage({super.key});
|
||||||
|
|
||||||
Future<void> _deleteKeyPair(BuildContext context) async {
|
void _deleteKeyPair(BuildContext context) {
|
||||||
final keyStorage = KeyStorage();
|
// Key deletion logic (not implemented here)
|
||||||
await keyStorage.deleteKeys();
|
// ...
|
||||||
|
|
||||||
|
// Show confirmation message
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(
|
const SnackBar(
|
||||||
content: Text('The key pair has been deleted.'),
|
content: Text('The key pair has been deleted.'),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Navigate back or update the UI as needed
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,8 +3,6 @@ import 'dart:typed_data';
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:pointycastle/export.dart' as crypto;
|
import 'package:pointycastle/export.dart' as crypto;
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'dart:io';
|
|
||||||
import 'key_storage.dart';
|
|
||||||
|
|
||||||
class ExportPrivateKeyPage extends StatefulWidget {
|
class ExportPrivateKeyPage extends StatefulWidget {
|
||||||
const ExportPrivateKeyPage({super.key});
|
const ExportPrivateKeyPage({super.key});
|
||||||
@ -17,41 +15,30 @@ class _ExportPrivateKeyPageState extends State<ExportPrivateKeyPage> {
|
|||||||
final TextEditingController _passwordController = TextEditingController();
|
final TextEditingController _passwordController = TextEditingController();
|
||||||
|
|
||||||
Future<void> _exportPrivateKey() async {
|
Future<void> _exportPrivateKey() async {
|
||||||
final keyStorage = KeyStorage();
|
// Replace with your actual private key retrieval logic
|
||||||
final privateKeyPem = await keyStorage.getPrivateKey();
|
final String privateKeyPem = 'Your private key here';
|
||||||
|
|
||||||
if (privateKeyPem == null) {
|
|
||||||
// Show error message if there's no key
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(
|
|
||||||
content: Text('No private key found to export.'),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Get the password from the user input
|
||||||
final password = _passwordController.text;
|
final password = _passwordController.text;
|
||||||
if (password.isEmpty) {
|
if (password.isEmpty) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
// Show error message
|
||||||
const SnackBar(
|
|
||||||
content: Text('Please enter a password.'),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encrypt the private key using AES-256
|
||||||
final encryptedData = _encryptPrivateKey(privateKeyPem, password);
|
final encryptedData = _encryptPrivateKey(privateKeyPem, password);
|
||||||
|
|
||||||
|
// Let the user pick a file location
|
||||||
final outputFile = await FilePicker.platform.saveFile(
|
final outputFile = await FilePicker.platform.saveFile(
|
||||||
dialogTitle: 'Save encrypted private key',
|
dialogTitle: 'Save encrypted private key',
|
||||||
fileName: 'private_key_encrypted.aes',
|
fileName: 'private_key_encrypted.aes',
|
||||||
);
|
);
|
||||||
|
|
||||||
if (outputFile != null) {
|
if (outputFile != null) {
|
||||||
try {
|
// Write the encrypted data to the file
|
||||||
final file = File(outputFile);
|
// Use appropriate file I/O methods (not shown here)
|
||||||
await file.writeAsBytes(encryptedData);
|
// ...
|
||||||
|
// Show a confirmation dialog or message
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
@ -65,33 +52,18 @@ class _ExportPrivateKeyPageState extends State<ExportPrivateKeyPage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} catch (e) {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
content: Text('Failed to write file: $e'),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Uint8List _encryptPrivateKey(String privateKey, String password) {
|
Uint8List _encryptPrivateKey(String privateKey, String password) {
|
||||||
// Derive a key from the password using PBKDF2
|
// Encryption logic using AES-256
|
||||||
final derivator = crypto.PBKDF2KeyDerivator(
|
final key = crypto.PBKDF2KeyDerivator(crypto.HMac(crypto.SHA256Digest(), 64))
|
||||||
crypto.HMac(crypto.SHA256Digest(), 64),
|
.process(Uint8List.fromList(utf8.encode(password)));
|
||||||
);
|
|
||||||
|
|
||||||
final salt = Uint8List.fromList(utf8.encode('some_salt')); // In production, use a random salt and store it securely
|
final params = crypto.PaddedBlockCipherParameters(
|
||||||
derivator.init(crypto.Pbkdf2Parameters(salt, 1000, 32));
|
crypto.ParametersWithIV(crypto.KeyParameter(key), Uint8List(16)), // Initialization Vector
|
||||||
final key = derivator.process(Uint8List.fromList(utf8.encode(password)));
|
|
||||||
|
|
||||||
// Initialize AES-CBC cipher with PKCS7 padding
|
|
||||||
final iv = Uint8List(16); // zero IV for example, in production use random IV and store it
|
|
||||||
final params = crypto.PaddedBlockCipherParameters<crypto.ParametersWithIV<crypto.KeyParameter>, Null>(
|
|
||||||
crypto.ParametersWithIV<crypto.KeyParameter>(crypto.KeyParameter(key), iv),
|
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
|
|
||||||
final cipher = crypto.PaddedBlockCipher('AES/CBC/PKCS7');
|
final cipher = crypto.PaddedBlockCipher('AES/CBC/PKCS7');
|
||||||
cipher.init(true, params);
|
cipher.init(true, params);
|
||||||
|
|
||||||
|
@ -4,12 +4,12 @@ import 'dart:math';
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'package:asn1lib/asn1lib.dart';
|
import 'package:asn1lib/asn1lib.dart';
|
||||||
import 'key_storage.dart';
|
|
||||||
|
|
||||||
class GenerateNewKeyPairPage extends StatelessWidget {
|
class GenerateNewKeyPairPage extends StatelessWidget {
|
||||||
const GenerateNewKeyPairPage({super.key});
|
const GenerateNewKeyPairPage({super.key});
|
||||||
|
|
||||||
Future<Map<String, String>> _generateKeyPair() async {
|
Future<Map<String, String>> _generateKeyPair() async {
|
||||||
|
// Key generation logic using pointycastle
|
||||||
final keyParams = crypto.RSAKeyGeneratorParameters(
|
final keyParams = crypto.RSAKeyGeneratorParameters(
|
||||||
BigInt.parse('65537'),
|
BigInt.parse('65537'),
|
||||||
2048,
|
2048,
|
||||||
@ -17,6 +17,8 @@ class GenerateNewKeyPairPage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final secureRandom = crypto.FortunaRandom();
|
final secureRandom = crypto.FortunaRandom();
|
||||||
|
|
||||||
|
// Seed the random number generator
|
||||||
final random = Random.secure();
|
final random = Random.secure();
|
||||||
final seeds = List<int>.generate(32, (_) => random.nextInt(256));
|
final seeds = List<int>.generate(32, (_) => random.nextInt(256));
|
||||||
secureRandom.seed(crypto.KeyParameter(Uint8List.fromList(seeds)));
|
secureRandom.seed(crypto.KeyParameter(Uint8List.fromList(seeds)));
|
||||||
@ -29,12 +31,11 @@ class GenerateNewKeyPairPage extends StatelessWidget {
|
|||||||
final publicKey = pair.publicKey as crypto.RSAPublicKey;
|
final publicKey = pair.publicKey as crypto.RSAPublicKey;
|
||||||
final privateKey = pair.privateKey as crypto.RSAPrivateKey;
|
final privateKey = pair.privateKey as crypto.RSAPrivateKey;
|
||||||
|
|
||||||
|
// Convert keys to PEM format
|
||||||
final publicKeyPem = _encodePublicKeyToPemPKCS1(publicKey);
|
final publicKeyPem = _encodePublicKeyToPemPKCS1(publicKey);
|
||||||
final privateKeyPem = _encodePrivateKeyToPemPKCS1(privateKey);
|
final privateKeyPem = _encodePrivateKeyToPemPKCS1(privateKey);
|
||||||
|
|
||||||
// Save keys securely
|
// Save keys securely (not implemented here)
|
||||||
final keyStorage = KeyStorage();
|
|
||||||
await keyStorage.saveKeys(publicKey: publicKeyPem, privateKey: privateKeyPem);
|
|
||||||
|
|
||||||
return {'publicKey': publicKeyPem, 'privateKey': privateKeyPem};
|
return {'publicKey': publicKeyPem, 'privateKey': privateKeyPem};
|
||||||
}
|
}
|
||||||
@ -51,8 +52,7 @@ class GenerateNewKeyPairPage extends StatelessWidget {
|
|||||||
|
|
||||||
Uint8List _encodePublicKeyToDer(crypto.RSAPublicKey publicKey) {
|
Uint8List _encodePublicKeyToDer(crypto.RSAPublicKey publicKey) {
|
||||||
final algorithmSeq = ASN1Sequence();
|
final algorithmSeq = ASN1Sequence();
|
||||||
// Create the OID directly with the arcs
|
algorithmSeq.add(ASN1ObjectIdentifier.fromName('rsaEncryption'));
|
||||||
algorithmSeq.add(ASN1ObjectIdentifier([1, 2, 840, 113549, 1, 1, 1]));
|
|
||||||
algorithmSeq.add(ASN1Null());
|
algorithmSeq.add(ASN1Null());
|
||||||
|
|
||||||
final publicKeySeq = ASN1Sequence();
|
final publicKeySeq = ASN1Sequence();
|
||||||
@ -84,8 +84,8 @@ class GenerateNewKeyPairPage extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _formatPem(Uint8List bytes, String label) {
|
String _formatPem(Uint8List bytes, String label) {
|
||||||
final base64Data = base64Encode(bytes);
|
final base64 = base64Encode(bytes);
|
||||||
final chunks = RegExp('.{1,64}').allMatches(base64Data).map((m) => m.group(0)!);
|
final chunks = RegExp('.{1,64}').allMatches(base64).map((m) => m.group(0)!);
|
||||||
return '-----BEGIN $label-----\n${chunks.join('\n')}\n-----END $label-----';
|
return '-----BEGIN $label-----\n${chunks.join('\n')}\n-----END $label-----';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,12 +99,13 @@ class GenerateNewKeyPairPage extends StatelessWidget {
|
|||||||
body: Center(
|
body: Center(
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await _generateKeyPair();
|
final keys = await _generateKeyPair();
|
||||||
|
// Display a confirmation dialog or message
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
title: const Text('Keys Generated'),
|
title: const Text('Keys Generated'),
|
||||||
content: const Text('The new key pair has been generated and stored securely.'),
|
content: const Text('The new key pair has been generated successfully.'),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(context),
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
// key_storage.dart
|
|
||||||
|
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
|
||||||
|
|
||||||
class KeyStorage {
|
|
||||||
static const _publicKeyKey = 'public_key';
|
|
||||||
static const _privateKeyKey = 'private_key';
|
|
||||||
|
|
||||||
final FlutterSecureStorage _storage = const FlutterSecureStorage();
|
|
||||||
|
|
||||||
Future<void> saveKeys({required String publicKey, required String privateKey}) async {
|
|
||||||
await _storage.write(key: _publicKeyKey, value: publicKey);
|
|
||||||
await _storage.write(key: _privateKeyKey, value: privateKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String?> getPublicKey() async {
|
|
||||||
return await _storage.read(key: _publicKeyKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String?> getPrivateKey() async {
|
|
||||||
return await _storage.read(key: _privateKeyKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> deleteKeys() async {
|
|
||||||
await _storage.delete(key: _publicKeyKey);
|
|
||||||
await _storage.delete(key: _privateKeyKey);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'show_public_key_qr.dart';
|
import 'package:dialer/features/settings/key/show_public_key_qr.dart';
|
||||||
import 'show_public_key_text.dart';
|
import 'package:dialer/features/settings/key/show_public_key_text.dart';
|
||||||
import 'generate_new_key_pair.dart';
|
import 'package:dialer/features/settings/key/generate_new_key_pair.dart';
|
||||||
import 'export_private_key.dart';
|
import 'package:dialer/features/settings/key/export_private_key.dart';
|
||||||
import 'delete_key_pair.dart';
|
import 'package:dialer/features/settings/key/delete_key_pair.dart';
|
||||||
|
|
||||||
class KeyManagementPage extends StatelessWidget {
|
class KeyManagementPage extends StatelessWidget {
|
||||||
const KeyManagementPage({super.key});
|
const KeyManagementPage({super.key});
|
||||||
@ -34,13 +34,14 @@ class KeyManagementPage extends StatelessWidget {
|
|||||||
MaterialPageRoute(builder: (context) => const ExportPrivateKeyPage()),
|
MaterialPageRoute(builder: (context) => const ExportPrivateKeyPage()),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'Delete a key pair':
|
case 'Delete a key pair, warning POPUP':
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(builder: (context) => const DeleteKeyPairPage()),
|
MaterialPageRoute(builder: (context) => const DeleteKeyPairPage()),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
// Handle default or unknown options
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,7 +53,7 @@ class KeyManagementPage extends StatelessWidget {
|
|||||||
'Display public key as QR code',
|
'Display public key as QR code',
|
||||||
'Generate a new key pair',
|
'Generate a new key pair',
|
||||||
'Export private key to password-encrypted file (AES 256)',
|
'Export private key to password-encrypted file (AES 256)',
|
||||||
'Delete a key pair',
|
'Delete a key pair, warning POPUP',
|
||||||
];
|
];
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
@ -1,48 +1,26 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:pretty_qr_code/pretty_qr_code.dart';
|
import 'package:pretty_qr_code/pretty_qr_code.dart';
|
||||||
import 'key_storage.dart';
|
|
||||||
|
|
||||||
class DisplayPublicKeyQRCodePage extends StatelessWidget {
|
class DisplayPublicKeyQRCodePage extends StatelessWidget {
|
||||||
const DisplayPublicKeyQRCodePage({super.key});
|
const DisplayPublicKeyQRCodePage({super.key});
|
||||||
|
|
||||||
Future<String?> _loadPublicKey() async {
|
|
||||||
final keyStorage = KeyStorage();
|
|
||||||
return keyStorage.getPublicKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
// Replace with your actual public key retrieval logic
|
||||||
|
final String publicKey = 'Your public key here';
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Public Key in QR Code'),
|
title: const Text('Public Key in QR Code'),
|
||||||
),
|
),
|
||||||
body: FutureBuilder<String?>(
|
body: Center(
|
||||||
future: _loadPublicKey(),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
||||||
return const Center(child: CircularProgressIndicator());
|
|
||||||
}
|
|
||||||
|
|
||||||
final publicKey = snapshot.data;
|
|
||||||
if (publicKey == null) {
|
|
||||||
return const Center(
|
|
||||||
child: Text(
|
|
||||||
'No public key found.',
|
|
||||||
style: TextStyle(color: Colors.white),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Center(
|
|
||||||
child: PrettyQr(
|
child: PrettyQr(
|
||||||
data: publicKey,
|
data: publicKey,
|
||||||
size: 250,
|
size: 250,
|
||||||
roundEdges: true,
|
roundEdges: true,
|
||||||
elementColor: Colors.white,
|
elementColor: Colors.white,
|
||||||
),
|
),
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,39 +1,19 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'key_storage.dart';
|
|
||||||
|
|
||||||
class DisplayPublicKeyTextPage extends StatelessWidget {
|
class DisplayPublicKeyTextPage extends StatelessWidget {
|
||||||
const DisplayPublicKeyTextPage({super.key});
|
const DisplayPublicKeyTextPage({super.key});
|
||||||
|
|
||||||
Future<String?> _loadPublicKey() async {
|
|
||||||
final keyStorage = KeyStorage();
|
|
||||||
return await keyStorage.getPublicKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
// Replace with your actual public key retrieval logic
|
||||||
|
final String publicKey = 'Your public key here';
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Public Key as Text'),
|
title: const Text('Public Key as Text'),
|
||||||
),
|
),
|
||||||
body: FutureBuilder<String?>(
|
body: Center(
|
||||||
future: _loadPublicKey(),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
||||||
return const Center(child: CircularProgressIndicator());
|
|
||||||
}
|
|
||||||
|
|
||||||
final publicKey = snapshot.data;
|
|
||||||
if (publicKey == null) {
|
|
||||||
return const Center(
|
|
||||||
child: Text(
|
|
||||||
'No public key found.',
|
|
||||||
style: TextStyle(color: Colors.white),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Center(
|
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: SelectableText(
|
child: SelectableText(
|
||||||
@ -42,8 +22,6 @@ class DisplayPublicKeyTextPage extends StatelessWidget {
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -17,13 +17,13 @@ class SettingsPage extends StatelessWidget {
|
|||||||
MaterialPageRoute(builder: (context) => const SettingsCallPage()),
|
MaterialPageRoute(builder: (context) => const SettingsCallPage()),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'Sim settings':
|
case 'Page of telephone accounts':
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(builder: (context) => const SettingsAccountsPage()),
|
MaterialPageRoute(builder: (context) => const SettingsAccountsPage()),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'Key management':
|
case 'Gestion de clés':
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(builder: (context) => const KeyManagementPage()),
|
MaterialPageRoute(builder: (context) => const KeyManagementPage()),
|
||||||
@ -54,7 +54,7 @@ class SettingsPage extends StatelessWidget {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Settings'),
|
title: const Text('settings'),
|
||||||
),
|
),
|
||||||
body: ListView.builder(
|
body: ListView.builder(
|
||||||
itemCount: settingsOptions.length,
|
itemCount: settingsOptions.length,
|
||||||
|
@ -7,13 +7,13 @@ class SettingsAccountsPage extends StatelessWidget {
|
|||||||
|
|
||||||
void _navigateToAccountOption(BuildContext context, String option) {
|
void _navigateToAccountOption(BuildContext context, String option) {
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case 'Chose SIM card':
|
case 'Choisir la SIM':
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(builder: (context) => const ChooseSimPage()),
|
MaterialPageRoute(builder: (context) => const ChooseSimPage()),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'SIM card parameters':
|
case 'Paramètre SIM':
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(builder: (context) => const SimParametersPage()),
|
MaterialPageRoute(builder: (context) => const SimParametersPage()),
|
||||||
@ -27,14 +27,14 @@ class SettingsAccountsPage extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final accountOptions = [
|
final accountOptions = [
|
||||||
'Chose SIM card',
|
'Choisir la SIM',
|
||||||
'SIM card parameters',
|
'Paramètre SIM',
|
||||||
];
|
];
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Sim settings'),
|
title: const Text('Page des comptes téléphoniques'),
|
||||||
),
|
),
|
||||||
body: ListView.builder(
|
body: ListView.builder(
|
||||||
itemCount: accountOptions.length,
|
itemCount: accountOptions.length,
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IDEDidComputeMac32BitWarning</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
7
dialer/macos/Runner.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "group:Runner.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IDEDidComputeMac32BitWarning</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@ -34,6 +34,7 @@ dependencies:
|
|||||||
|
|
||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
|
url_launcher: ^6.1.9 # To manage system dialer. Call, message...
|
||||||
shared_preferences: ^2.3.3 # Local storage (no critical data)
|
shared_preferences: ^2.3.3 # Local storage (no critical data)
|
||||||
cupertino_icons: ^1.0.8
|
cupertino_icons: ^1.0.8
|
||||||
flutter_contacts: ^1.1.9+2
|
flutter_contacts: ^1.1.9+2
|
||||||
@ -45,11 +46,9 @@ dependencies:
|
|||||||
mobile_scanner: ^6.0.2
|
mobile_scanner: ^6.0.2
|
||||||
pretty_qr_code: ^3.3.0
|
pretty_qr_code: ^3.3.0
|
||||||
pointycastle: ^3.4.0
|
pointycastle: ^3.4.0
|
||||||
file_picker: ^8.1.6
|
file_picker: ^5.2.5
|
||||||
asn1lib: ^1.0.0
|
asn1lib: ^1.0.0
|
||||||
intl_utils: ^2.0.7
|
intl_utils: ^2.0.7
|
||||||
url_launcher: ^6.3.1
|
|
||||||
flutter_secure_storage: ^9.0.0
|
|
||||||
mobile_number:
|
mobile_number:
|
||||||
path: packages/mobile_number
|
path: packages/mobile_number
|
||||||
|
|
||||||
|
5
docs/.gitignore
vendored
@ -1,5 +0,0 @@
|
|||||||
*
|
|
||||||
!*.md
|
|
||||||
!*.pdf
|
|
||||||
!*.sh
|
|
||||||
!.gitignore
|
|
@ -1,72 +0,0 @@
|
|||||||
# Icing
|
|
||||||
|
|
||||||
An Epitech Innovation Project
|
|
||||||
|
|
||||||
*By*
|
|
||||||
**Bartosz Michalak - Alexis Danlos - Florian Griffon - Ange Duhayon - Stéphane Corbière**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
- [Introduction to Icing](#introducingtoicing)
|
|
||||||
- [Strategy](#icingsstrategy)
|
|
||||||
- [Technology choices]()
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Introduction to Icing
|
|
||||||
|
|
||||||
Icing is the name of our project, which is divided in **two interconnected goals**:
|
|
||||||
1. Provide an end-to-end (E2E) encryption **code library**, based on Eliptic Curve Cryptography (ECC), to encrypt phone-calls on an **analog audio** level.
|
|
||||||
2. Provide a reference implementation in the form of a totally seamless Android **smartphone dialer** application, that anybody could use without being aware of its encryption feature.
|
|
||||||
|
|
||||||
This idea came naturally to our minds, when we remarked the lack of such tool.
|
|
||||||
|
|
||||||
Where "private messaging" and other "encrypted communication" apps flourish, nowadays, they **all** require an internet access to work.
|
|
||||||
|
|
||||||
### Privacy and security in telecoms should not depend on internet availability.
|
|
||||||
|
|
||||||
We are conscious that ourselves, and our surroundings, grew up in Global North, with simple and cheap internet and telecommunication access, but we should not forget that on a global point of view, it is estimated that less than 20% of the world's stepable land is covered with 3G/4G/+ network.
|
|
||||||
Standard "low-tech" GSM network coverage is almost twice that.
|
|
||||||
|
|
||||||
So in a real-world, stressful and harsh condition, affording privacy or security in telecommunication is usually too much of a luxury; and we should change that.
|
|
||||||
|
|
||||||
Our solution is for the every-man that is not even aware of its smart phone weakness, as well as for the activists or journalists surviving in hostile environment around the globe.
|
|
||||||
|
|
||||||
|
|
||||||
### Setting a new security standard
|
|
||||||
|
|
||||||
#### ***"There is no way to create a backdoor that only the good guys can walk through"***
|
|
||||||
> (*Meredith Whittaker - President of Signal Fundation - July 2023, Channel 4*)
|
|
||||||
|
|
||||||
If the police can listen to your calls with a mandate, hackers can, without mandate.
|
|
||||||
|
|
||||||
Many online platforms, such as online bank accounts, uses phone calls, or voicemails to drop security codes needed for authentication. The idea is to bring extra security, by requiring a second factor to authenticate the user, but most voicemails security features have been obsolete for a long time now.
|
|
||||||
|
|
||||||
**But this could change with globalized end-to-end encryption.**
|
|
||||||
|
|
||||||
This not only enables obfuscation of the transmitted audio data, but also hard peer authentication.
|
|
||||||
This means that if you are in an important call, where you could communicate sensitive information such as passwords, or financial orders, using Icing protocol you and your peer would know that there is no man in the middle, listening and stealing information, and that your correspondent really is who it says.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Icing's strategy
|
|
||||||
|
|
||||||
We focus on FOSS community as a primary target.
|
|
||||||
|
|
||||||
Our reference implementation, the Iced dialer, is destined to replace any stock dialer app from any android smartphone.
|
|
||||||
|
|
||||||
Alternative open-source and privacy-focused Android distributions, such as GrapheneOS, are major targets.
|
|
||||||
|
|
||||||
Their community are thriving, and could help our open-source development.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Technology choices
|
|
||||||
|
|
||||||
We chose to code with Flutter, the Dart framework.
|
|
||||||
Even though this choice gives us quick-delivery capabilities, we will need to switch language for lower levels development, such as sound stream caption, encryption, compression, encoding, and transmission.
|
|
||||||
|
|
||||||
The language for these manoeuvres is not determined yet, but Go, Rust, Kotlin and Java are good candidates.
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
|||||||
---
|
|
||||||
marp: true
|
|
||||||
_class: lead
|
|
||||||
paginate: true
|
|
||||||
---
|
|
||||||
<!-- theme: uncover -->
|
|
||||||
<!-- class: invert -->
|
|
||||||
|
|
||||||
# Icing
|
|
||||||
|
|
||||||
#### Epitech Inovative Project
|
|
||||||
|
|
||||||
##### https://git.gmoker.com/icing
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Florian** Griffon
|
|
||||||
|
|
||||||
**Bartosz** Michalak
|
|
||||||
|
|
||||||
**Ange** Duhayon
|
|
||||||
|
|
||||||
**Alexis** Danlos
|
|
||||||
|
|
||||||
**Stéphane** Corbière
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# :phone: :man:
|
|
||||||
|
|
|
||||||
|
|
|
||||||
:smiling_imp:
|
|
||||||
|
|
|
||||||
|
|
|
||||||
# :phone: :woman:
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# :phone: :man:
|
|
||||||
**|** | **|**
|
|
||||||
**|** | **|**
|
|
||||||
**|** | **|** :imp:
|
|
||||||
**|** | **|**
|
|
||||||
**|** | **|**
|
|
||||||
# :phone: :woman:
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Un client téléphonique comme un autre
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## L'utilisateur est le maître de sa sécurité
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Partage de contacts par QR codes
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Intégration harmonieuse d'un chiffrement automatique
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Protection d'appel téléphoniques =
|
|
||||||
|
|
||||||
##### :white_check_mark: Conservation de vie privée
|
|
||||||
##### :white_check_mark: Protection de données sensibles
|
|
||||||
##### :white_check_mark: Protection d'authentification
|
|
||||||
##### :white_check_mark: Protection de la messagerie
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## **Icing Dialer**
|
|
||||||
|
|
||||||
### =
|
|
||||||
|
|
||||||
### **Icing protocol**
|
|
||||||
|
|
||||||
**+**
|
|
||||||
|
|
||||||
### **Dialer**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Icing est un **outil**, pas un produit
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Merci
|
|
BIN
docs/Pitch.pdf
@ -1,71 +0,0 @@
|
|||||||
|
|
||||||
# User Manual
|
|
||||||
|
|
||||||
|
|
||||||
**Utilization documentation.**
|
|
||||||
|
|
||||||
Written with chapters for the average Joe user, security experts, and developers.
|
|
||||||
|
|
||||||
The average-user section is only about what the average-user will know from Icing: its dialer reference implementation.
|
|
||||||
|
|
||||||
The security expert section will cover all the theory behind our reference implementation, and the Icing protocol. This section can serve as an introduction / transition for the next section:
|
|
||||||
|
|
||||||
The developer section will explain our code architecture and concepts, going in-depth inside the reference implementation and the Icing protocol library.
|
|
||||||
This library will have dedicated documentation in this section, so any developer can implement it in any desired way.
|
|
||||||
|
|
||||||
Lastly, as a continuation of the developer section, the Manual Test section will cover our manual testing policy.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- [Average User](#averageuser)
|
|
||||||
|
|
||||||
- [Security Expert](#icingsstrategy)
|
|
||||||
|
|
||||||
- [Developer](#developer)
|
|
||||||
|
|
||||||
- [Manual Tests](#manualtests)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Average User
|
|
||||||
|
|
||||||
|
|
||||||
Use the Icing dialer like your normal dialer, if you can't do that we can't help, you dumb retard lmfao.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Security Expert
|
|
||||||
|
|
||||||
SecUriTy eXpeRt
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Developer
|
|
||||||
|
|
||||||
int main;
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Manual Tests
|
|
||||||
|
|
||||||
1. Call grandpa
|
|
||||||
2. Receive mum call
|
|
||||||
3. Order 150g of 95% pure Bolivian coke without encryption
|
|
||||||
4. Order again but with encryption
|
|
||||||
5. Compare results
|
|
@ -1,6 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
IMG=docker.io/marpteam/marp-cli:latest
|
|
||||||
|
|
||||||
docker run --rm -v "$PWD:/home/marp/app/" --entrypoint marp-cli.js "$IMG" \
|
|
||||||
./Pitch.md --pdf
|
|
@ -1 +0,0 @@
|
|||||||
PROD_URL=icing.gmoker.com
|
|
42
website/.gitignore
vendored
@ -1,27 +1,23 @@
|
|||||||
# Created by https://www.toptal.com/developers/gitignore/api/go
|
.DS_Store
|
||||||
# Edit at https://www.toptal.com/developers/gitignore?templates=go
|
node_modules
|
||||||
|
/dist
|
||||||
|
|
||||||
### Go ###
|
|
||||||
# If you prefer the allow list template instead of the deny list, see community template:
|
|
||||||
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
|
||||||
#
|
|
||||||
# Binaries for programs and plugins
|
|
||||||
*.exe
|
|
||||||
*.exe~
|
|
||||||
*.dll
|
|
||||||
*.so
|
|
||||||
*.dylib
|
|
||||||
|
|
||||||
# Test binary, built with `go test -c`
|
# local env files
|
||||||
*.test
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
# Log files
|
||||||
*.out
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
# Dependency directories (remove the comment below to include it)
|
# Editor directories and files
|
||||||
# vendor/
|
.idea
|
||||||
|
.vscode
|
||||||
# Go workspace file
|
*.suo
|
||||||
go.work
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
# End of https://www.toptal.com/developers/gitignore/api/go
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
ARG VER=1.23
|
|
||||||
|
|
||||||
FROM "docker.io/golang:$VER" as build
|
|
||||||
WORKDIR /build/
|
|
||||||
ARG VER
|
|
||||||
COPY main.go .
|
|
||||||
RUN printf "module main\ngo $VER" > go.mod && CGO_ENABLED=0 go build -o /app
|
|
||||||
|
|
||||||
FROM scratch
|
|
||||||
COPY --from=build /app /app
|
|
||||||
COPY static/ /static/
|
|
||||||
COPY html/ /html/
|
|
||||||
EXPOSE 3000
|
|
||||||
CMD ["/app"]
|
|
24
website/README.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# my-vue-app
|
||||||
|
|
||||||
|
## Project setup
|
||||||
|
```
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compiles and hot-reloads for development
|
||||||
|
```
|
||||||
|
npm run serve
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compiles and minifies for production
|
||||||
|
```
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Lints and fixes files
|
||||||
|
```
|
||||||
|
npm run lint
|
||||||
|
```
|
||||||
|
|
||||||
|
### Customize configuration
|
||||||
|
See [Configuration Reference](https://cli.vuejs.org/config/).
|
5
website/babel.config.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module.exports = {
|
||||||
|
presets: [
|
||||||
|
'@vue/cli-plugin-babel/preset'
|
||||||
|
]
|
||||||
|
}
|
@ -1,6 +0,0 @@
|
|||||||
---
|
|
||||||
services:
|
|
||||||
app:
|
|
||||||
build: .
|
|
||||||
ports:
|
|
||||||
- "3000:3000"
|
|
@ -1,229 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Icing</title>
|
|
||||||
<!-- <link rel="stylesheet" href="style.css"/> -->
|
|
||||||
<style>
|
|
||||||
/* Theme colors */
|
|
||||||
:root {
|
|
||||||
--primary-color: #000000; /* Green accent color */
|
|
||||||
--background-color: #f5f5f5; /* Light background */
|
|
||||||
--text-color: #333; /* Dark text */
|
|
||||||
--secondary-text-color: #777; /* Secondary text color */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Base styles */
|
|
||||||
.content {
|
|
||||||
margin: 20px auto;
|
|
||||||
max-width: 900px;
|
|
||||||
padding: 40px;
|
|
||||||
background-color: var(--background-color);
|
|
||||||
color: var(--text-color);
|
|
||||||
border-radius: 8px;
|
|
||||||
font-family: 'Open Sans', Arial, sans-serif;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 2.5em;
|
|
||||||
color: var(--primary-color);
|
|
||||||
margin-bottom: 30px;
|
|
||||||
text-align: center;
|
|
||||||
animation: fadeInDown 1s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-title {
|
|
||||||
font-size: 1.8em;
|
|
||||||
color: var(--primary-color);
|
|
||||||
margin-top: 40px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
position: relative;
|
|
||||||
animation: fadeInLeft 1s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-title::after {
|
|
||||||
content: '';
|
|
||||||
width: 50px;
|
|
||||||
height: 3px;
|
|
||||||
background-color: var(--primary-color);
|
|
||||||
position: absolute;
|
|
||||||
bottom: -10px;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
p, li {
|
|
||||||
line-height: 1.6;
|
|
||||||
font-size: 1.1em;
|
|
||||||
animation: fadeIn 1s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul {
|
|
||||||
margin-left: 20px;
|
|
||||||
list-style-type: disc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.features ul li {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.team-list {
|
|
||||||
list-style-type: none;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.team-list li {
|
|
||||||
margin-bottom: 8px;
|
|
||||||
font-weight: bold;
|
|
||||||
color: var(--text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.back-link-container {
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 40px;
|
|
||||||
animation: fadeInUp 1s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.back-link {
|
|
||||||
text-decoration: none;
|
|
||||||
color: var(--primary-color);
|
|
||||||
font-weight: bold;
|
|
||||||
border: 2px solid var(--primary-color);
|
|
||||||
padding: 10px 20px;
|
|
||||||
border-radius: 5px;
|
|
||||||
transition: background-color 0.3s, color 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.back-link:hover {
|
|
||||||
background-color: var(--primary-color);
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeInDown {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(-20px);
|
|
||||||
} to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeInLeft {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateX(-20px);
|
|
||||||
} to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeInUp {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(20px);
|
|
||||||
} to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeIn {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
} to {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Responsive Design */
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.content {
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-title {
|
|
||||||
font-size: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
p, li {
|
|
||||||
font-size: 1em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 480px) {
|
|
||||||
.content {
|
|
||||||
padding: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 1.8em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-title {
|
|
||||||
font-size: 1.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
p, li {
|
|
||||||
font-size: 0.9em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: var(--primary-color);
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="description" class="content">
|
|
||||||
<h1 class="title">Project Description</h1>
|
|
||||||
|
|
||||||
<div class="project-overview">
|
|
||||||
<h2 class="section-title">What is Icing?</h2>
|
|
||||||
<p>
|
|
||||||
Icing is a simple, lightweight, and efficient dialer designed to replace your everyday phone app. It ensures end-to-end encryption of telephone communications by implementing a home-made, analogic-based voice encryption. Inspired by SRTP (Secure Real-time Transport Protocol), using ECDH (Elliptic Curve Diffie-Hellman).
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="features">
|
|
||||||
<h2 class="section-title">Key Features</h2>
|
|
||||||
<ul>
|
|
||||||
<li><strong>End-to-End Encryption:</strong> Secure your calls with robust encryption protocols.</li>
|
|
||||||
<li><strong>Transparent:</strong> If your peer doesn't use Icing, the call remains completely normal.</li>
|
|
||||||
<li><strong>Analogic-based:</strong> An open-source, exportable, protocol that <strong>works without internet.</strong></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="how-it-works">
|
|
||||||
<h2 class="section-title">How It Works</h2>
|
|
||||||
<p>
|
|
||||||
Icing generates a cryptographic key pair for you. Share your public key with a neat QR code.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
During a call between two Icing users, voices are encrypted, compressed, and transmitted via the telephone network using the Icing Acoustic Protocol.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="team">
|
|
||||||
<h2 class="section-title">Our Team</h2>
|
|
||||||
<p>
|
|
||||||
We are a team of five dedicated individuals working on this solution:
|
|
||||||
</p>
|
|
||||||
<ul class="team-list">
|
|
||||||
<li><a href="https://github.com/AlexisDanlos/" target="_blank">Alexis Danlos</a></li>
|
|
||||||
<li><a href="https://github.com/AustralEpitech/" target="_blank">AustralEpitech</a></li>
|
|
||||||
<li><a href="https://github.com/Bartoszkk/" target="_blank">Bartoszkk</a></li>
|
|
||||||
<li><a href="https://github.com/FlorianGRIFFON/" target="_blank">Florian GRIFFON</a></li>
|
|
||||||
<li><a href="https://github.com/STCB/" target="_blank">STCB</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<style>
|
|
||||||
.centered {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 100vh;
|
|
||||||
font-size: 3em;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-underline {
|
|
||||||
text-decoration: none;
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="home">
|
|
||||||
<h1 class="centered">
|
|
||||||
<router-link to="/description" class="no-underline">ICING</router-link>
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
19
website/jsconfig.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"module": "esnext",
|
||||||
|
"baseUrl": "./",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"src/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"lib": [
|
||||||
|
"esnext",
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"scripthost"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -1,32 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
func route(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.URL.Path == "/style.css" {
|
|
||||||
http.ServeFile(w, r, "/html/style.css")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(r.URL.Path) > len("/static/") && r.URL.Path[:len("/static/")] == "/static/" {
|
|
||||||
http.ServeFile(w, r, r.URL.Path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r.URL.Path == "/" {
|
|
||||||
http.ServeFile(w, r, "/html/index.html")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
http.ServeFile(w, r, filepath.Join("/html", r.URL.Path + ".html"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
http.HandleFunc("/", route)
|
|
||||||
|
|
||||||
err := http.ListenAndServe(":3000", nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
#!/bin/bash -e
|
|
||||||
set -o pipefail
|
|
||||||
|
|
||||||
function kapply() {
|
|
||||||
for f in "$@"; do
|
|
||||||
kubectl apply -f \
|
|
||||||
<(envsubst "$(env | xargs printf '$%s ')" < "manifests/$f")
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
function kcreatesec() {
|
|
||||||
kubectl create secret generic --save-config --dry-run=client -oyaml "$@" | kubectl apply -f-
|
|
||||||
}
|
|
||||||
|
|
||||||
function kcreatecm() {
|
|
||||||
kubectl create configmap --dry-run=client -oyaml "$@" | kubectl apply -f-
|
|
||||||
}
|
|
||||||
|
|
||||||
function kgseckey() {
|
|
||||||
local sec="$1"; shift
|
|
||||||
local key="$1"; shift
|
|
||||||
|
|
||||||
kubectl get secret "$sec" -o jsonpath="{.data.$key}" | base64 -d
|
|
||||||
}
|
|
||||||
|
|
||||||
function kgcmkey() {
|
|
||||||
local cm="$1"; shift
|
|
||||||
local key="$1"; shift
|
|
||||||
|
|
||||||
kubectl get configmap "$cm" -o jsonpath="{.data.$key}"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
kapply common/app.yaml
|
|
||||||
|
|
||||||
kubectl rollout restart deployment app
|
|
@ -1,5 +0,0 @@
|
|||||||
#!/bin/bash -e
|
|
||||||
|
|
||||||
export NB_REPLICAS=1
|
|
||||||
|
|
||||||
. ./manifests/bin/deploy.sh
|
|
@ -1,5 +0,0 @@
|
|||||||
#!/bin/bash -e
|
|
||||||
|
|
||||||
export NB_REPLICAS=3
|
|
||||||
|
|
||||||
. ./manifests/bin/deploy.sh
|
|
@ -1,64 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
name: app
|
|
||||||
annotations:
|
|
||||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
|
||||||
spec:
|
|
||||||
ingressClassName: nginx
|
|
||||||
tls:
|
|
||||||
- secretName: tls-app
|
|
||||||
hosts:
|
|
||||||
- "$BASE_URL"
|
|
||||||
rules:
|
|
||||||
- host: "$BASE_URL"
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- path: /
|
|
||||||
pathType: Prefix
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: app
|
|
||||||
port:
|
|
||||||
name: http
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: app
|
|
||||||
labels:
|
|
||||||
app: app
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
app: app
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
port: 80
|
|
||||||
targetPort: http
|
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: app
|
|
||||||
labels:
|
|
||||||
app: app
|
|
||||||
spec:
|
|
||||||
replicas: $NB_REPLICAS
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: app
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: app
|
|
||||||
spec:
|
|
||||||
imagePullSecrets:
|
|
||||||
- name: regcred
|
|
||||||
containers:
|
|
||||||
- name: app
|
|
||||||
image: "$IMAGEAPP"
|
|
||||||
imagePullPolicy: Always
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
containerPort: 3000
|
|
20230
website/package-lock.json
generated
Normal file
44
website/package.json
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"name": "my-vue-app",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"serve": "vue-cli-service serve",
|
||||||
|
"build": "vue-cli-service build",
|
||||||
|
"lint": "vue-cli-service lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"core-js": "^3.8.3",
|
||||||
|
"vue": "^3.2.13",
|
||||||
|
"vue-router": "^4.4.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.12.16",
|
||||||
|
"@babel/eslint-parser": "^7.12.16",
|
||||||
|
"@vue/cli-plugin-babel": "~5.0.0",
|
||||||
|
"@vue/cli-plugin-eslint": "~5.0.0",
|
||||||
|
"@vue/cli-service": "~5.0.0",
|
||||||
|
"eslint": "^7.32.0",
|
||||||
|
"eslint-plugin-vue": "^8.0.3"
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"root": true,
|
||||||
|
"env": {
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"plugin:vue/vue3-essential",
|
||||||
|
"eslint:recommended"
|
||||||
|
],
|
||||||
|
"parserOptions": {
|
||||||
|
"parser": "@babel/eslint-parser"
|
||||||
|
},
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"> 1%",
|
||||||
|
"last 2 versions",
|
||||||
|
"not dead",
|
||||||
|
"not ie 11"
|
||||||
|
]
|
||||||
|
}
|
BIN
website/public/favicon.ico
Normal file
After Width: | Height: | Size: 4.2 KiB |
17
website/public/index.html
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
|
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<noscript>
|
||||||
|
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||||
|
</noscript>
|
||||||
|
<div id="app"></div>
|
||||||
|
<!-- built files will be auto injected -->
|
||||||
|
</body>
|
||||||
|
</html>
|
19
website/src/App.vue
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<!-- App.vue -->
|
||||||
|
<template>
|
||||||
|
<div id="app">
|
||||||
|
<router-view></router-view>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'App',
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* Global styles can be added here */
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
</style>
|
BIN
website/src/assets/logo.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
58
website/src/components/HelloWorld.vue
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<template>
|
||||||
|
<div class="hello">
|
||||||
|
<h1>{{ msg }}</h1>
|
||||||
|
<p>
|
||||||
|
For a guide and recipes on how to configure / customize this project,<br>
|
||||||
|
check out the
|
||||||
|
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
|
||||||
|
</p>
|
||||||
|
<h3>Installed CLI Plugins</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
|
||||||
|
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
|
||||||
|
</ul>
|
||||||
|
<h3>Essential Links</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
|
||||||
|
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
|
||||||
|
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
|
||||||
|
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
|
||||||
|
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
|
||||||
|
</ul>
|
||||||
|
<h3>Ecosystem</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
|
||||||
|
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
|
||||||
|
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
|
||||||
|
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
|
||||||
|
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'HelloWorld',
|
||||||
|
props: {
|
||||||
|
msg: String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||||
|
<style scoped>
|
||||||
|
h3 {
|
||||||
|
margin: 40px 0 0;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: #42b983;
|
||||||
|
}
|
||||||
|
</style>
|
36
website/src/components/HomePage.vue
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<!-- src/components/Home.vue -->
|
||||||
|
<template>
|
||||||
|
<div id="home">
|
||||||
|
<h1 class="centered">
|
||||||
|
<router-link to="/description" class="no-underline">ICING</router-link>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'HomePage',
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.centered {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100vh;
|
||||||
|
font-size: 3em;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-underline {
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
230
website/src/components/ProjectDescription.vue
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
<!-- src/components/Description.vue -->
|
||||||
|
<template>
|
||||||
|
<div id="description" class="content">
|
||||||
|
<h1 class="title">Project Description</h1>
|
||||||
|
|
||||||
|
<div class="project-overview">
|
||||||
|
<h2 class="section-title">What is Icing?</h2>
|
||||||
|
<p>
|
||||||
|
Icing is a simple, lightweight, and efficient dialer designed to replace your everyday phone app. It ensures end-to-end encryption of telephone communications by implementing a home-made, analogic-based voice encryption. Inspired by SRTP (Secure Real-time Transport Protocol), using ECDH (Elliptic Curve Diffie-Hellman).
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="features">
|
||||||
|
<h2 class="section-title">Key Features</h2>
|
||||||
|
<ul>
|
||||||
|
<li><strong>End-to-End Encryption:</strong> Secure your calls with robust encryption protocols.</li>
|
||||||
|
<li><strong>Transparent:</strong> If your peer doesn't use Icing, the call remains completely normal.</li>
|
||||||
|
<li><strong>Analogic-based:</strong> An open-source, exportable, protocol that <strong>works without internet.</strong></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="how-it-works">
|
||||||
|
<h2 class="section-title">How It Works</h2>
|
||||||
|
<p>
|
||||||
|
Icing generates a cryptographic key pair for you. Share your public key with a neat QR code.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
During a call between two Icing users, voices are encrypted, compressed, and transmitted via the telephone network using the Icing Acoustic Protocol.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="team">
|
||||||
|
<h2 class="section-title">Our Team</h2>
|
||||||
|
<p>
|
||||||
|
We are a team of five dedicated individuals working on this solution:
|
||||||
|
</p>
|
||||||
|
<ul class="team-list">
|
||||||
|
<li><a href="https://github.com/Bartoszkk/" target="_blank">Bartoszkk</a></li>
|
||||||
|
<li><a href="https://github.com/AustralEpitech/" target="_blank">AustralEpitech</a></li>
|
||||||
|
<li><a href="https://github.com/STCB/" target="_blank">STCB</a></li>
|
||||||
|
<li><a href="https://github.com/FlorianGRIFFON/" target="_blank">Florian GRIFFON</a></li>
|
||||||
|
<li><a href="https://github.com/AlexisDanlos/" target="_blank">Alexis Danlos</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'ProjectDescription',
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* Theme colors */
|
||||||
|
:root {
|
||||||
|
--primary-color: #000000; /* Green accent color */
|
||||||
|
--background-color: #f5f5f5; /* Light background */
|
||||||
|
--text-color: #333; /* Dark text */
|
||||||
|
--secondary-text-color: #777; /* Secondary text color */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Base styles */
|
||||||
|
.content {
|
||||||
|
margin: 20px auto;
|
||||||
|
max-width: 900px;
|
||||||
|
padding: 40px;
|
||||||
|
background-color: var(--background-color);
|
||||||
|
color: var(--text-color);
|
||||||
|
border-radius: 8px;
|
||||||
|
font-family: 'Open Sans', Arial, sans-serif;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 2.5em;
|
||||||
|
color: var(--primary-color);
|
||||||
|
margin-bottom: 30px;
|
||||||
|
text-align: center;
|
||||||
|
animation: fadeInDown 1s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 1.8em;
|
||||||
|
color: var(--primary-color);
|
||||||
|
margin-top: 40px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
position: relative;
|
||||||
|
animation: fadeInLeft 1s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title::after {
|
||||||
|
content: '';
|
||||||
|
width: 50px;
|
||||||
|
height: 3px;
|
||||||
|
background-color: var(--primary-color);
|
||||||
|
position: absolute;
|
||||||
|
bottom: -10px;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p, li {
|
||||||
|
line-height: 1.6;
|
||||||
|
font-size: 1.1em;
|
||||||
|
animation: fadeIn 1s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
margin-left: 20px;
|
||||||
|
list-style-type: disc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.features ul li {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-list {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-list li {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-link-container {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 40px;
|
||||||
|
animation: fadeInUp 1s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-link {
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--primary-color);
|
||||||
|
font-weight: bold;
|
||||||
|
border: 2px solid var(--primary-color);
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
transition: background-color 0.3s, color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-link:hover {
|
||||||
|
background-color: var(--primary-color);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInDown {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-20px);
|
||||||
|
} to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInLeft {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(-20px);
|
||||||
|
} to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInUp {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
} to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
} to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive Design */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.content {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
p, li {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.content {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 1.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
p, li {
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--primary-color);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
</style>
|
6
website/src/main.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// src/main.js
|
||||||
|
import { createApp } from 'vue';
|
||||||
|
import App from './App.vue';
|
||||||
|
import router from './router';
|
||||||
|
|
||||||
|
createApp(App).use(router).mount('#app');
|
24
website/src/router.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// src/router.js
|
||||||
|
import { createRouter, createWebHistory } from 'vue-router';
|
||||||
|
import HomePage from './components/HomePage.vue';
|
||||||
|
import ProjectDescription from './components/ProjectDescription.vue';
|
||||||
|
|
||||||
|
const routes = [
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
name: 'HomePage',
|
||||||
|
component: HomePage,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/description',
|
||||||
|
name: 'ProjectDescription',
|
||||||
|
component: ProjectDescription,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const router = createRouter({
|
||||||
|
history: createWebHistory(),
|
||||||
|
routes,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
Before Width: | Height: | Size: 1.2 KiB |
4
website/vue.config.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
const { defineConfig } = require('@vue/cli-service')
|
||||||
|
module.exports = defineConfig({
|
||||||
|
transpileDependencies: true
|
||||||
|
})
|