Remove deprecated mobile_notworking.del project files and configurations

This commit is contained in:
louiscklaw
2025-06-13 12:45:09 +08:00
parent 5651150c9d
commit 542691f4fd
635 changed files with 0 additions and 65577 deletions

Submodule 03_source/mobile.compile_ok deleted from 69f0997a27

View File

@@ -1,15 +0,0 @@
# http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false

View File

@@ -1,2 +0,0 @@
VITE_SUPABASE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE
VITE_SUPABASE_URL=http://192.168.10.89:8000

View File

@@ -1,5 +0,0 @@
{
"projects": {
"default": "ionic-react-conference-app"
}
}

View File

@@ -1,93 +0,0 @@
**/*log
**/*log.*
**/*del
**/*del.*
**/*copy*
*copy*
**/_backup/*
**/*bak
**/*bak.*
# Logs
.firebase
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# See https://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
/node_modules
# testing
/coverage
# production
/dist
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.stencil/

View File

@@ -1 +0,0 @@
/* /index.html 200

View File

@@ -1,3 +0,0 @@
{
"siteId": "86675615-6271-4145-8ffe-9c78dc4d34a3"
}

View File

@@ -1 +0,0 @@
**/_backup

View File

@@ -1,34 +0,0 @@
module.exports = {
arrowParens: 'avoid',
bracketSpacing: true,
htmlWhitespaceSensitivity: 'strict',
insertPragma: false,
jsxBracketSameLine: false,
jsxSingleQuote: false,
printWidth: 120,
proseWrap: 'preserve',
quoteProps: 'as-needed',
requirePragma: false,
semi: true,
singleQuote: true,
tabWidth: 2,
trailingComma: 'all',
useTabs: false,
endOfLine: 'lf',
//
overrides: [
{
files: ['*.yml'],
options: {
singleQuote: false,
},
},
{
files: ['*.md', '*.mdx'],
options: {
useTabs: false,
},
},
],
plugins: [require.resolve('prettier-plugin-organize-imports')],
};

View File

@@ -1,5 +0,0 @@
{
"javascript.updateImportsOnFileMove.enabled": "always",
"typescript.updateImportsOnFileMove.enabled": "always",
"git.ignoreLimitWarning": true
}

View File

@@ -1 +0,0 @@
FROM node:20-bullseye-slim

View File

@@ -1,23 +0,0 @@
Copyright 2015-present Drifty Co.
http://drifty.com/
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -1,59 +0,0 @@
# Ionic React Conference Application
This application is purely a kitchen-sink demo of the Ionic Framework and React.
**There is not an actual Ionic Conference at this time.** This project is just to show off Ionic components in a real-world application.
## Angular and Vue versions
We've built versions of this Conference app in Angular and Vue for developers that would prefer to use one of those framework options:
https://github.com/ionic-team/ionic-conference-app
https://github.com/ionic-team/ionic-vue-conference-app
## Table of Contents
- [Getting Started](#getting-started)
- [App Preview](#app-preview)
## Getting Started
- [Download the installer](https://nodejs.org/) for Node LTS.
- Install the ionic CLI globally: `npm install -g ionic`
- Clone this repository: `git clone https://github.com/ionic-team/ionic-react-conference-app.git`.
- Run `npm install` from the project root.
- Run `ionic serve` in a terminal from the project root.
- Profit. :tada:
## App Preview
### [Menu](https://github.com/ionic-team/ionic-react-conference-app/blob/main/src/components/Menu.tsx)
| Material Design | iOS |
| -------------------------------------------------------- | ------------------------------------------------ |
| ![Android Menu](/resources/screenshots/android-menu.png) | ![iOS Menu](/resources/screenshots/ios-menu.png) |
### [Schedule Page](https://github.com/ionic-team/ionic-react-conference-app/blob/main/src/pages/SchedulePage.tsx)
| Material Design | iOS |
| ---------------------------------------------------------------- | -------------------------------------------------------- |
| ![Android Schedule](/resources/screenshots/android-schedule.png) | ![iOS Schedule](/resources/screenshots/ios-schedule.png) |
### [Speakers Page](https://github.com/ionic-team/ionic-react-conference-app/blob/main/src/pages/SpeakerList.tsx)
| Material Design | iOS |
| ---------------------------------------------------------------- | -------------------------------------------------------- |
| ![Android Speakers](/resources/screenshots/android-speakers.png) | ![iOS Speakers](/resources/screenshots/ios-speakers.png) |
### [Speaker Detail Page](https://github.com/ionic-team/ionic-react-conference-app/blob/main/src/pages/SpeakerDetail.tsx)
| Material Design | iOS |
| ---------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| ![Android Speaker Detail](/resources/screenshots/android-speaker-detail.png) | ![iOS Speaker Detail](/resources/screenshots/ios-speaker-detail.png) |
### [About Page](https://github.com/ionic-team/ionic-react-conference-app/blob/main/src/pages/About.tsx)
| Material Design | iOS |
| ---------------------------------------------------------- | -------------------------------------------------- |
| ![Android About](/resources/screenshots/android-about.png) | ![iOS About](/resources/screenshots/ios-about.png) |

View File

@@ -1,14 +0,0 @@
// Only used for jest
module.exports = {
presets: [
[
'@babel/preset-env',
{
targets: {
node: 'current',
},
},
],
'@babel/preset-typescript',
],
};

View File

@@ -1,63 +0,0 @@
const execSync = require('child_process').execSync;
const fs = require('fs');
const path = require('path');
// const chalk = require('chalk');
// Function to get all subdirectories of a given directory
function getDirectories(srcPath, excludeDirs) {
return fs
.readdirSync(srcPath)
.filter(file => !excludeDirs.includes(file) && fs.lstatSync(path.join(srcPath, file)).isDirectory())
.map(name => path.join(srcPath, name));
}
// Get current working directory
const cwd = process.cwd();
const backup_dir = path.join(cwd, '_backup');
// Path to app-head directory
const appHeadDir = path.join(cwd, 'src');
// Check if app-head exists
if (!fs.existsSync(appHeadDir)) {
console.error(`Error: ${appHeadDir} does not exist.`);
process.exit(1);
}
// Execute reset.bat scripts
try {
// execSync(`cmd /c "cd ${appHeadDir} && scripts\\reset.bat"`, { stdio: 'inherit' });
} catch (err) {
console.error(`Error executing reset.bat script: ${err.message}`);
process.exit(1);
}
// Define excluded directories
const excludedDirs = ['.next', 'node_modules', '.git', 'volumes', '_mp4'];
// Copy app-head directory and its contents to a new directory with an increasing number suffix
let maxNum = 0;
const directories = getDirectories(backup_dir, excludedDirs);
for (const dir of directories) {
const match = dir.match(/^.+draft-(\d+).*$/);
if (match) {
const num = parseInt(match[1], 10);
if (num > maxNum) {
maxNum = num;
}
}
}
var zerofilled = ('0000' + (maxNum + 1)).slice(-4);
const targetDir = path.join(backup_dir, `draft-${zerofilled}`);
fs.mkdirSync(targetDir);
// Copy app-head directory and its contents to targetDir, excluding specified directories
fs.cpSync(appHeadDir, targetDir, {
filter: src => !excludedDirs.includes(path.basename(src)),
recursive: true,
});
console.log(' DONE DONE DONE \n' + ' DONE DONE DONE \n' + ' DONE DONE DONE \n');
console.log(`Successfully backup to ${targetDir}.`);

View File

@@ -1,8 +0,0 @@
{
"appId": "io.ionic.starter",
"appName": "ionic-react-conference-app",
"bundledWebRuntime": false,
"npmClient": "npm",
"webDir": "dist",
"cordova": {}
}

View File

@@ -1,7 +0,0 @@
#!/usr/bin/env bash
set -ex
docker compose up -d
docker compose exec -it mobile bash

View File

@@ -1,11 +0,0 @@
name: 009_poc_chatroom_implement
services:
mobile:
build: .
ports:
- 3000:3000
command: sleep infinity
volumes:
- .:/app
working_dir: /app

View File

@@ -1,31 +0,0 @@
{
"hosting": {
"public": "build",
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
],
"headers": [
{
"source": "**/static/**",
"headers": [
{
"key": "Cache-Control",
"value": "max-age=31536000"
}
]
},
{
"source": "**/*.@(jpg|jpeg|gif|png|svg)",
"headers": [
{
"key": "Cache-Control",
"value": "max-age=31536000"
}
]
}
]
}
}

View File

@@ -1,32 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Ionic Conference App</title>
<meta
name="viewport"
content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<meta name="format-detection" content="telephone=no" />
<meta name="msapplication-tap-highlight" content="no" />
<link rel="manifest" href="/manifest.json" />
<link rel="shortcut icon" type="image/png" href="/assets/icon/favicon.png" />
<!-- add to homescreen for ios -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-title" content="Ionic Conference App" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
<script
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAmAwkv8-x2I--ne-NtA3C_4E_-xLCsFJs"
async
defer
></script>
</body>
</html>

View File

@@ -1,7 +0,0 @@
{
"name": "ionic-react-conference-app",
"integrations": {
"capacitor": {}
},
"type": "react"
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,76 +0,0 @@
{
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"dependencies": {
"@capacitor/camera": "^4.1.5",
"@capacitor/core": "^4.6.1",
"@capacitor/preferences": "^4.0.2",
"@ionic/pwa-elements": "^3.3.0",
"@ionic/react": "8.2.6",
"@ionic/react-router": "8.2.6",
"@supabase/auth-helpers-nextjs": "^0.9.0",
"@supabase/auth-helpers-react": "^0.3.1",
"@supabase/ssr": "latest",
"@supabase/supabase-js": "2.44.0",
"date-fns": "^2.25.0",
"dayjs": "^1.11.13",
"i18next": "^22.4.14",
"i18next-browser-languagedetector": "^7.0.1",
"ionicons": "^7.1.2",
"lodash": "^4.17.21",
"prettier-plugin-organize-imports": "^4.0.0",
"pullstate": "^1.22.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^12.2.0",
"react-markdown": "^9.0.1",
"react-router": "^5.3.4",
"react-router-dom": "^5.3.4",
"react-use": "^17.2.4",
"reselect": "^4.0.0",
"sass": "^1.59.3",
"swiper": "^9.1.1",
"typescript": "5.3.3"
},
"description": "An Ionic project",
"devDependencies": {
"@capacitor/cli": "^4.6.1",
"@testing-library/react": "^9.3.1",
"@types/googlemaps": "^3.38.0",
"@types/jest": "24.0.18",
"@types/node": "20.11.5",
"@types/react": "18.2.48",
"@types/react-dom": "18.2.18",
"@types/react-router": "^5.1.20",
"@types/react-router-dom": "^5.3.3",
"@vitejs/plugin-legacy": "^5.4.1",
"@vitejs/plugin-react": "^4.3.1",
"lint-staged": "^13.2.0",
"prettier": "^2.8.6",
"vite": "^5.4.0"
},
"eslintConfig": {
"extends": "react-app"
},
"lint-staged": {
"src/**/*.{js,jsx,ts,tsx,json,md}": [
"prettier --write",
"git add"
]
},
"name": "ionic-react-conference-app",
"private": true,
"scripts": {
"build": "tsc && vite build",
"dev": "vite --host 0.0.0.0 --cors --force --strictPort",
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,json,md}\"",
"precommit": "npm run format && lint-staged",
"preview": "vite preview",
"start": "npm run dev"
},
"version": "0.0.1"
}

View File

@@ -1,55 +0,0 @@
歡迎使用香港單身派對!本服務協議及社區規範(以下簡稱“協議”)旨在規範您使用香港單身派對(以下簡稱“平台”)的行為,確保平台的健康運營和用戶的良好體驗。請在使用平台前仔細閱讀並遵守本協議。
1. 服務內容
香港單身派對提供以下服務:
(a) 附近的人交友:使用地理定位功能幫助您認識附近的用戶。
(b) 線上活動參與:平台不定期舉辦各類線上活動,包括但不限於遊戲配對、主題討論和社交聚會。
2. 用戶權利與義務
(a) 用戶有權使用平台提供的服務,並參與平台組織的活動。
(b) 用戶應確保其在平台上發布的個人照片及資料真實且屬於本人,不得使用他人的照片或虛假信息。
(c) 用戶應遵守相關法律法規,不得利用平台進行任何非法活動。
(d) 用戶應尊重其他用戶的隱私權和個人信息安全,不得收集、使用或披露其他用戶的信息。
(e) 用戶應維護良好的社區環境,不得發布任何違背公序良俗、含有歧視、騷擾、暴力或色情等內容的信息。
(f) 用戶不得抄襲、模仿或以其他方式侵犯平台的知識產權,包括但不限於應用程序的界面設計、功能實現和內容創作。
(g) 本平台僅限於 18 歲以上的用戶使用。未滿 18 歲的用戶不得使用平台,一旦發現,其帳號將被終止。
3. 社區規範
(a) 禁止發布任何形式的廣告、垃圾信息或欺詐信息。
(b) 用戶應保持友好互動,避免使用侮辱性、攻擊性的語言。
(c) 用戶不得發布、傳播任何侵犯他人知識產權或其他合法權益的信息。
(d) 用戶應遵守平台的操作規範,不得進行任何破壞平台正常運行的行為。
4. 隱私保護
平台將採取合理措施保護用戶的個人信息,並遵守相關隱私保護法律法規。用戶同意平台在提供服務過程中收集和使用其個人信息。
5. 違規處理
用戶違反本協議時,平台將視情節輕重給予警告或終止其帳號的使用權。嚴重違反者將被永久禁止使用平台服務。
6. 協議的變更與終止
(a) 平台有權根據需要對本協議進行修改,並在平台上公佈最新版本。
(b) 如用戶違反本協議,平台有權限制或終止其使用平台的權利。
7. 爭議解決
因本協議引起的任何爭議,雙方應首先嘗試友好協商解決;協商不成時,任何一方可直接提出訴訟。
8. 其他
(a) 本平台保留對所有情況的最終決定權和解釋權。
(b) 本協議的附件是協議不可分割的一部分,與協議具有同等法律效力。
用戶在使用平台服務時,即表示已閱讀、理解並同意遵守本協議。
~ 完 ~

View File

@@ -1,53 +0,0 @@
歡迎使用香港單身派對!本服務協議及社區規範(以下簡稱“協議”)旨在規範您使用香港單身派對(以下簡稱“平台”)的行為,確保平台的健康運營和用戶的良好體驗。請在使用平台前仔細閱讀並遵守本協議。
1. 服務內容
香港單身派對提供以下服務:
(a) 附近的人交友:使用地理定位功能幫助您認識附近的用戶。
(b) 線上活動參與:平台不定期舉辦各類線上活動,包括但不限於遊戲配對、主題討論和社交聚會。
2. 用戶權利與義務
(a) 用戶有權使用平台提供的服務,並參與平台組織的活動。
(b) 用戶應確保其在平台上發布的個人照片及資料真實且屬於本人,不得使用他人的照片或虛假信息。
(c) 用戶應遵守相關法律法規,不得利用平台進行任何非法活動。
(d) 用戶應尊重其他用戶的隱私權和個人信息安全,不得收集、使用或披露其他用戶的信息。
(e) 用戶應維護良好的社區環境,不得發布任何違背公序良俗、含有歧視、騷擾、暴力或色情等內容的信息。
(f) 用戶不得抄襲、模仿或以其他方式侵犯平台的知識產權,包括但不限於應用程序的界面設計、功能實現和內容創作。
(g) 本平台僅限於 18 歲以上的用戶使用。未滿 18 歲的用戶不得使用平台,一旦發現,其帳號將被終止。
3. 社區規範
(a) 禁止發布任何形式的廣告、垃圾信息或欺詐信息。
(b) 用戶應保持友好互動,避免使用侮辱性、攻擊性的語言。
(c) 用戶不得發布、傳播任何侵犯他人知識產權或其他合法權益的信息。
(d) 用戶應遵守平台的操作規範,不得進行任何破壞平台正常運行的行為。
4. 隱私保護
平台將採取合理措施保護用戶的個人信息,並遵守相關隱私保護法律法規。用戶同意平台在提供服務過程中收集和使用其個人信息。
5. 違規處理
用戶違反本協議時,平台將視情節輕重給予警告或終止其帳號的使用權。嚴重違反者將被永久禁止使用平台服務。
6. 協議的變更與終止
(a) 平台有權根據需要對本協議進行修改,並在平台上公佈最新版本。
(b) 如用戶違反本協議,平台有權限制或終止其使用平台的權利。
7. 爭議解決
因本協議引起的任何爭議,雙方應首先嘗試友好協商解決;協商不成時,任何一方可直接提出訴訟。
8. 其他
(a) 本平台保留對所有情況的最終決定權和解釋權。
(b) 本協議的附件是協議不可分割的一部分,與協議具有同等法律效力。
用戶在使用平台服務時,即表示已閱讀、理解並同意遵守本協議。

View File

@@ -1,45 +0,0 @@
## Privacy Policy
Welcome to Hong Kong Single Party. We understand the importance of privacy to you and are committed to taking all reasonable measures to protect your personal information. This Privacy Policy aims to explain how we collect, use, store, and protect your personal information, as well as the rights you have regarding your information.
1. Collection of Personal Information
To provide the best social experience, we may collect the following types of personal information when you use [Friend Circle]:
- Basic Information: Such as your name, gender, date of birth, phone number, and email address.
- Location Information: When you enable location services, we may collect information about the location of your device to recommend nearby activities and friends.
- Usage Information: Including the time, frequency, preference settings, and interaction data of your use of [Friend Circle].
- Activity Participation Information: When you participate in our offline activities, we may collect information about your participation and feedback.
2. Use of Personal Information
We use your personal information mainly for the following purposes:
- Service Provision and Improvement: To ensure that [Friend Circle] functions properly and to continuously optimize and improve it.
- Personalized Experience: To provide you with a more personalized service and recommendations based on your preferences and usage habits.
- Activity Organization: To organize and arrange offline activities that interest you, including game matching and social gatherings.
- Communication: To send you important notifications, such as activity updates, new features, or customer service-related information.
- Security: To protect the security of your account and to prevent and investigate potential security issues.
3. Storage and Protection of Personal Information
We will take appropriate technical and organizational measures to protect your personal information against unauthorized access, disclosure, alteration, or destruction. We will store your personal information on secure servers and restrict employee access to this information.
4. Sharing and Transfer of Personal Information
We will not sell or provide your personal information to third parties unless:
- We have your explicit consent.
- It is necessary to share information with trusted third-party partners to provide a service or feature you have requested.
- Required by law or to comply with legal processes.
5. Your Rights
You have the following rights regarding your personal information:
- Right to Access: You have the right to access the personal information we hold about you.
- Right to Rectification: You have the right to request corrections if you find any inaccuracies in the information we hold.
- Right to Erasure: Under certain circumstances, you have the right to request the deletion of your personal information.
6. Policy Updates
We may update this Privacy Policy from time to time. All updates will be published within the [Friend Circle] application and will be reflected in the new effective date of the updated Privacy Policy.
7. Contact Us
If you have any questions or concerns about this Privacy Policy, or if you wish to exercise any of the above rights, please contact us using “Contact us”of Hong Kong Single party. Our team will respond as soon as possible. Please wait.
Hong Kong Single Party. We will continue to strive to provide you with a safer and more reliable social experience.

View File

@@ -1,45 +0,0 @@
## Privacy Policy
Welcome to Hong Kong Single Party. We understand the importance of privacy to you and are committed to taking all reasonable measures to protect your personal information. This Privacy Policy aims to explain how we collect, use, store, and protect your personal information, as well as the rights you have regarding your information.
1. Collection of Personal Information
To provide the best social experience, we may collect the following types of personal information when you use [Friend Circle]:
- Basic Information: Such as your name, gender, date of birth, phone number, and email address.
- Location Information: When you enable location services, we may collect information about the location of your device to recommend nearby activities and friends.
- Usage Information: Including the time, frequency, preference settings, and interaction data of your use of [Friend Circle].
- Activity Participation Information: When you participate in our offline activities, we may collect information about your participation and feedback.
2. Use of Personal Information
We use your personal information mainly for the following purposes:
- Service Provision and Improvement: To ensure that [Friend Circle] functions properly and to continuously optimize and improve it.
- Personalized Experience: To provide you with a more personalized service and recommendations based on your preferences and usage habits.
- Activity Organization: To organize and arrange offline activities that interest you, including game matching and social gatherings.
- Communication: To send you important notifications, such as activity updates, new features, or customer service-related information.
- Security: To protect the security of your account and to prevent and investigate potential security issues.
3. Storage and Protection of Personal Information
We will take appropriate technical and organizational measures to protect your personal information against unauthorized access, disclosure, alteration, or destruction. We will store your personal information on secure servers and restrict employee access to this information.
4. Sharing and Transfer of Personal Information
We will not sell or provide your personal information to third parties unless:
- We have your explicit consent.
- It is necessary to share information with trusted third-party partners to provide a service or feature you have requested.
- Required by law or to comply with legal processes.
5. Your Rights
You have the following rights regarding your personal information:
- Right to Access: You have the right to access the personal information we hold about you.
- Right to Rectification: You have the right to request corrections if you find any inaccuracies in the information we hold.
- Right to Erasure: Under certain circumstances, you have the right to request the deletion of your personal information.
6. Policy Updates
We may update this Privacy Policy from time to time. All updates will be published within the [Friend Circle] application and will be reflected in the new effective date of the updated Privacy Policy.
7. Contact Us
If you have any questions or concerns about this Privacy Policy, or if you wish to exercise any of the above rights, please contact us using “Contact us”of Hong Kong Single party. Our team will respond as soon as possible. Please wait.
Hong Kong Single Party. We will continue to strive to provide you with a safer and more reliable social experience.

View File

@@ -1,467 +0,0 @@
{
"schedule": [
{
"date": "2047-05-17",
"groups": [
{
"time": "8:00 am",
"sessions": [
{
"name": "Breakfast",
"timeStart": "8:00 am",
"timeEnd": "9:00 am",
"location": "Dining Hall",
"tracks": ["Food"],
"id": "1"
}
]
},
{
"time": "9:15 am",
"sessions": [
{
"name": "Getting Started with Ionic",
"location": "Hall 2",
"description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, well provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. Well also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.",
"speakerNames": ["Ted Turtle"],
"timeStart": "9:30 am",
"timeEnd": "9:45 am",
"tracks": ["Ionic"],
"id": "2"
},
{
"name": "Ionic Tooling",
"location": "Executive Ballroom",
"description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, well provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. Well also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.",
"speakerNames": ["Rachel Rabbit"],
"timeStart": "9:45 am",
"timeEnd": "10:00 am",
"tracks": ["Tooling"],
"id": "3"
},
{
"name": "University of Ionic",
"location": "Hall 3",
"description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, well provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. Well also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.",
"speakerNames": ["Ellie Elephant"],
"timeStart": "9:15 am",
"timeEnd": "9:30 am",
"tracks": ["Ionic"],
"id": "4"
}
]
},
{
"time": "10:00 am",
"sessions": [
{
"name": "Migrating to Ionic",
"location": "Hall 1",
"description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, well provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. Well also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.",
"speakerNames": ["Eva Eagle", "Lionel Lion"],
"timeStart": "10:00 am",
"timeEnd": "10:15 am",
"tracks": ["Ionic"],
"id": "5"
},
{
"name": "What's New in Angular",
"location": "Hall 3",
"description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, well provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. Well also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.",
"speakerNames": ["Rachel Rabbit"],
"timeStart": "10:15 am",
"timeEnd": "10:30 am",
"tracks": ["Angular"],
"id": "6"
},
{
"name": "The Evolution of Ionicons",
"location": "Hall 2",
"description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, well provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. Well also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.",
"speakerNames": ["Isabella Iguana", "Eva Eagle"],
"timeStart": "10:15 am",
"timeEnd": "10:30 am",
"tracks": ["Design"],
"id": "7"
},
{
"name": "Ionic Pro",
"location": "Grand Ballroom A",
"description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, well provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. Well also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.",
"speakerNames": ["Charlie Cheetah"],
"timeStart": "10:45 am",
"timeEnd": "11:00 am",
"tracks": ["Services"],
"id": "8"
}
]
},
{
"time": "11:00 am",
"sessions": [
{
"name": "Ionic Workshop",
"location": "Hall 1",
"description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, well provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. Well also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.",
"speakerNames": ["Karl Kitten", "Lionel Lion"],
"timeStart": "11:00 am",
"timeEnd": "11:45 am",
"tracks": ["Workshop"],
"id": "9"
},
{
"name": "Community Interaction",
"location": "Hall 3",
"description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, well provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. Well also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.",
"speakerNames": ["Lionel Lion", "Gino Giraffe"],
"timeStart": "11:30 am",
"timeEnd": "11:50 am",
"tracks": ["Communication"],
"id": "10"
},
{
"name": "Navigation in Ionic",
"location": "Grand Ballroom A",
"description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, well provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. Well also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.",
"speakerNames": ["Rachel Rabbit", "Eva Eagle"],
"timeStart": "11:30 am",
"timeEnd": "12:00 pm",
"tracks": ["Navigation"],
"id": "11"
}
]
},
{
"time": "12:00 pm",
"sessions": [
{
"name": "Lunch",
"location": "Dining Hall",
"description": "Come grab lunch with all the Ionic fanatics and talk all things Ionic",
"timeStart": "12:00 pm",
"timeEnd": "1:00 pm",
"tracks": ["Food"],
"id": "12"
}
]
},
{
"time": "1:00 pm",
"sessions": [
{
"name": "Ionic in the Enterprise",
"location": "Hall 1",
"description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, well provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. Well also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.",
"speakerNames": ["Paul Puppy"],
"timeStart": "1:00 pm",
"timeEnd": "1:15 pm",
"tracks": ["Communication"],
"id": "13"
},
{
"name": "Ionic Worldwide",
"location": "Hall 1",
"description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, well provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. Well also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.",
"speakerNames": ["Gino Giraffe"],
"timeStart": "1:15 pm",
"timeEnd": "1:30 pm",
"tracks": ["Communication"],
"id": "14"
},
{
"name": "The Ionic Package",
"location": "Grand Ballroom B",
"description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, well provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. Well also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.",
"speakerNames": ["Molly Mouse", "Burt Bear"],
"timeStart": "1:30 pm",
"timeEnd": "2:00 pm",
"tracks": ["Services"],
"id": "15"
}
]
},
{
"time": "2:00 pm",
"sessions": [
{
"name": "Push Notifications in Ionic",
"location": "Hall 2",
"description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, well provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. Well also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.",
"speakerNames": ["Burt Bear", "Charlie Cheetah"],
"timeStart": "2:00 pm",
"timeEnd": "2:30 pm",
"tracks": ["Services"],
"id": "16"
},
{
"name": "Ionic Documentation",
"location": "Grand Ballroom B",
"description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, well provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. Well also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.",
"speakerNames": ["Donald Duck"],
"timeStart": "2:30 pm",
"timeEnd": "2:45 pm",
"tracks": ["Documentation"],
"id": "17"
},
{
"name": "UX in Ionic",
"location": "Hall 3",
"description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, well provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. Well also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.",
"speakerNames": ["Isabella Iguana", "Ellie Elephant"],
"timeStart": "2:45 pm",
"timeEnd": "3:00 pm",
"tracks": ["Design"],
"id": "18"
}
]
},
{
"time": "3:00",
"sessions": [
{
"name": "Angular Directives in Ionic",
"location": "Hall 1",
"description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, well provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. Well also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.",
"speakerNames": ["Ted Turtle"],
"timeStart": "3:00 pm",
"timeEnd": "3:30 pm",
"tracks": ["Angular"],
"id": "19"
},
{
"name": "Mobile States",
"location": "Hall 2",
"description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, well provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. Well also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.",
"speakerNames": ["Rachel Rabbit"],
"timeStart": "3:30 pm",
"timeEnd": "3:45 pm",
"tracks": ["Navigation"],
"id": "20"
}
]
}
]
}
],
"speakers": [
{
"name": "Burt Bear",
"profilePic": "/assets/img/speakers/bear.jpg",
"instagram": "ionicframework",
"twitter": "ionicframework",
"about": "Burt is a Bear. Burt's interests include poetry, dashing space heroes, and lions.",
"title": "Software Engineer",
"location": "Everywhere",
"email": "burt@example.com",
"phone": "+1-541-754-3010",
"id": "1"
},
{
"name": "Charlie Cheetah",
"profilePic": "/assets/img/speakers/cheetah.jpg",
"instagram": "ionicframework",
"twitter": "ionicframework",
"about": "Charlie is a Cheetah. Charlie's interests include country music, plush animals, pyrotechnics, and skeletons.",
"title": "Software Engineer",
"location": "Everywhere",
"email": "charlie@example.com",
"phone": "+1-541-754-3010",
"id": "2"
},
{
"name": "Donald Duck",
"profilePic": "/assets/img/speakers/duck.jpg",
"instagram": "ionicframework",
"twitter": "ionicframework",
"about": "Donald is a Duck. Donald's interests include carpentry, superheroes, merpeople, and glam rock.",
"title": "Software Engineer",
"location": "Everywhere",
"email": "donald@example.com",
"phone": "+1-541-754-3010",
"id": "3"
},
{
"name": "Eva Eagle",
"profilePic": "/assets/img/speakers/eagle.jpg",
"instagram": "ionicframework",
"twitter": "ionicframework",
"about": "Eva is an Eagle. Eva's interests include ants, seashells, and cupcakes.",
"title": "Developer Advocate",
"location": "Everywhere",
"email": "eva@example.com",
"phone": "+1-541-754-3010",
"id": "4"
},
{
"name": "Ellie Elephant",
"profilePic": "/assets/img/speakers/elephant.jpg",
"instagram": "ionicframework",
"twitter": "ionicframework",
"about": "Ellie is an Elephant. Ellie's interests include pocket watches, pool, hand fans, and ninjas.",
"title": "Software Engineer",
"location": "Everywhere",
"email": "ellie@example.com",
"phone": "+1-541-754-3010",
"id": "5"
},
{
"name": "Gino Giraffe",
"profilePic": "/assets/img/speakers/giraffe.jpg",
"instagram": "ionicframework",
"twitter": "ionicframework",
"about": "Gino is a Giraffe. Gino's interests include candy-making, unicorns, and birdhouses.",
"title": "Software Engineer",
"location": "Everywhere",
"email": "gino@example.com",
"phone": "+1-541-754-3010",
"id": "6"
},
{
"name": "Isabella Iguana",
"profilePic": "/assets/img/speakers/iguana.jpg",
"instagram": "ionicframework",
"twitter": "ionicframework",
"about": "Isabella is an Iguana. Isabella's interests include crystals, architecture, and candle-making.",
"title": "Software Engineer",
"location": "Everywhere",
"email": "isabella@example.com",
"phone": "+1-541-754-3010",
"id": "7"
},
{
"name": "Karl Kitten",
"profilePic": "/assets/img/speakers/kitten.jpg",
"instagram": "ionicframework",
"twitter": "ionicframework",
"about": "Karl is a Kitten. Karl's interests include skiing, jewelry, and needlepoint.",
"title": "Developer Advocate",
"location": "Everywhere",
"email": "karl@example.com",
"phone": "+1-541-754-3010",
"id": "8"
},
{
"name": "Lionel Lion",
"profilePic": "/assets/img/speakers/lion.jpg",
"instagram": "ionicframework",
"twitter": "ionicframework",
"about": "Lionel is a Lion. Lionel's interests include lizards and mathematics.",
"title": "Developer Advocate",
"location": "Everywhere",
"email": "lionel@example.com",
"phone": "+1-541-754-3010",
"id": "9"
},
{
"name": "Molly Mouse",
"profilePic": "/assets/img/speakers/mouse.jpg",
"instagram": "ionicframework",
"twitter": "ionicframework",
"about": "Molly is a Mouse. Molly's interests include werewolves and magic.",
"title": "Software Engineer",
"location": "Everywhere",
"email": "molly@example.com",
"phone": "+1-541-754-3010",
"id": "10"
},
{
"name": "Paul Puppy",
"profilePic": "/assets/img/speakers/puppy.jpg",
"instagram": "ionicframework",
"twitter": "ionicframework",
"about": "Paul is a Puppy. Paul's interests include maps, whales, and dragons.",
"title": "Software Engineer",
"location": "Everywhere",
"email": "paul@example.com",
"phone": "+1-541-754-3010",
"id": "11"
},
{
"name": "Rachel Rabbit",
"profilePic": "/assets/img/speakers/rabbit.jpg",
"instagram": "ionicframework",
"twitter": "ionicframework",
"about": "Rachel is a Rabbit. Rachel's interests include clowns, skeletons, and yo-yos.",
"title": "Senior Software Engineer",
"location": "Everywhere",
"email": "rachel@example.com",
"phone": "+1-541-754-3010",
"id": "12"
},
{
"name": "Ted Turtle",
"profilePic": "/assets/img/speakers/turtle.jpg",
"instagram": "ionicframework",
"twitter": "ionicframework",
"about": "Ted is a Turtle. Ted's interests include butterflies, skiing, and cupcakes.",
"title": "Software Engineer",
"location": "Everywhere",
"email": "ted@example.com",
"phone": "+1-541-754-3010",
"id": "13"
}
],
"map": [
{
"name": "Monona Terrace Convention Center",
"lat": 43.071584,
"lng": -89.38012,
"center": true
},
{
"name": "Ionic HQ",
"lat": 43.074395,
"lng": -89.381056
},
{
"name": "Afterparty - Brocach Irish Pub",
"lat": 43.07336,
"lng": -89.38335
}
],
"tracks": [
{
"name": "Angular",
"icon": "logo-angular"
},
{
"name": "Documentation",
"icon": "document"
},
{
"name": "Food",
"icon": "restaurant"
},
{
"name": "Ionic",
"icon": "logo-ionic"
},
{
"name": "Tooling",
"icon": "hammer"
},
{
"name": "Design",
"icon": "color-palette"
},
{
"name": "Services",
"icon": "cog"
},
{
"name": "Workshop",
"icon": "construct"
},
{
"name": "Communication",
"icon": "call"
},
{
"name": "Navigation",
"icon": "compass"
}
]
}

View File

@@ -1,26 +0,0 @@
[
{
"id": 1,
"name": "Map Center",
"lat": 43.071584,
"lng": -89.38012
},
{
"id": 2,
"name": "Monona Terrace Convention Center",
"lat": 43.071584,
"lng": -89.38012
},
{
"id": 3,
"name": "Ionic HQ",
"lat": 43.074395,
"lng": -89.381056
},
{
"id": 4,
"name": "Afterparty - Brocach Irish Pub",
"lat": 43.07336,
"lng": -89.38335
}
]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1004 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 599 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 700 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,2 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#3880FF" d="M256 139.3c-64.3 0-116.7 52.3-116.7 116.7 0 64.3 52.3 116.7 116.7 116.7S372.7 320.3 372.7 256 320.3 139.3 256 139.3z"/><circle fill="#3880FF" cx="423.5" cy="96.5" r="53.2"/><path fill="#3880FF" d="M489 149.9l-2.2-4.9-3.6 4c-8.7 9.9-19.8 17.5-32.1 22.1l-3.4 1.3 1.4 3.3c10.6 25.5 16 52.5 16 80.2 0 115.3-93.8 209.2-209.2 209.2S46.8 371.3 46.8 256 140.7 46.8 256 46.8c31.3 0 61.5 6.8 89.6 20.2l3.3 1.6 1.4-3.3c5.1-12 13.3-22.7 23.6-31l4.2-3.4-4.8-2.5C336.8 9.6 297.3 0 256 0 114.8 0 0 114.8 0 256s114.8 256 256 256 256-114.8 256-256c0-36.9-7.7-72.6-23-106.1z"/></svg>

Before

Width:  |  Height:  |  Size: 655 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#FFF" d="M256 139.3c-64.3 0-116.7 52.3-116.7 116.7 0 64.3 52.3 116.7 116.7 116.7S372.7 320.3 372.7 256 320.3 139.3 256 139.3z"/><circle fill="#FFF" cx="423.5" cy="96.5" r="53.2"/><path fill="#FFF" d="M489 149.9l-2.2-4.9-3.6 4c-8.7 9.9-19.8 17.5-32.1 22.1l-3.4 1.3 1.4 3.3c10.6 25.5 16 52.5 16 80.2 0 115.3-93.8 209.2-209.2 209.2S46.8 371.3 46.8 256 140.7 46.8 256 46.8c31.3 0 61.5 6.8 89.6 20.2l3.3 1.6 1.4-3.3c5.1-12 13.3-22.7 23.6-31l4.2-3.4-4.8-2.5C336.8 9.6 297.3 0 256 0 114.8 0 0 114.8 0 256s114.8 256 256 256 256-114.8 256-256c0-36.9-7.7-72.6-23-106.1z"/></svg>

Before

Width:  |  Height:  |  Size: 643 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 910 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -1 +0,0 @@
<svg width="350" height="140" xmlns="http://www.w3.org/2000/svg" style="background:#f6f7f9"><g fill="none" fill-rule="evenodd"><path fill="#F04141" style="mix-blend-mode:multiply" d="M61.905-34.23l96.194 54.51-66.982 54.512L22 34.887z"/><circle fill="#10DC60" style="mix-blend-mode:multiply" cx="155.5" cy="135.5" r="57.5"/><path fill="#3880FF" style="mix-blend-mode:multiply" d="M208.538 9.513l84.417 15.392L223.93 93.93z"/><path fill="#FFCE00" style="mix-blend-mode:multiply" d="M268.625 106.557l46.332-26.75 46.332 26.75v53.5l-46.332 26.75-46.332-26.75z"/><circle fill="#7044FF" style="mix-blend-mode:multiply" cx="299.5" cy="9.5" r="38.5"/><rect fill="#11D3EA" style="mix-blend-mode:multiply" transform="rotate(-60 148.47 37.886)" x="143.372" y="-7.056" width="10.196" height="89.884" rx="5.098"/><path d="M-25.389 74.253l84.86 8.107c5.498.525 9.53 5.407 9.004 10.905a10 10 0 0 1-.057.477l-12.36 85.671a10.002 10.002 0 0 1-11.634 8.42l-86.351-15.226c-5.44-.959-9.07-6.145-8.112-11.584l13.851-78.551a10 10 0 0 1 10.799-8.219z" fill="#7044FF" style="mix-blend-mode:multiply"/><circle fill="#0CD1E8" style="mix-blend-mode:multiply" cx="273.5" cy="106.5" r="20.5"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -1,21 +0,0 @@
{
"short_name": "Ionic React Conf",
"name": "Ionic React Conf",
"icons": [
{
"src": "assets/icon/favicon.png",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "assets/icon/icon.png",
"type": "image/png",
"sizes": "512x512",
"purpose": "maskable"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#ffffff",
"background_color": "#ffffff"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 730 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 740 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 KiB

View File

@@ -1,6 +0,0 @@
/*
* App Global CSS
* ----------------------------------------------------------------------------
* Put style rules here that you want to apply globally. These styles are for
* the entire app and not just one component.
*/

View File

@@ -1,7 +0,0 @@
import { render } from '@testing-library/react';
import App from './App';
it('renders without crashing', () => {
const { asFragment, container } = render(<App />);
expect(asFragment()).toMatchSnapshot();
});

View File

@@ -1,273 +0,0 @@
import { IonApp, IonNav, IonRouterOutlet, IonSplitPane, setupIonicReact } from '@ionic/react';
import { IonReactRouter } from '@ionic/react-router';
import React, { useContext, useEffect } from 'react';
import { Route } from 'react-router-dom';
import Menu from './components/Menu';
/* Core CSS required for Ionic components to work properly */
import '@ionic/react/css/core.css';
/* Basic CSS for apps built with Ionic */
import '@ionic/react/css/normalize.css';
import '@ionic/react/css/structure.css';
import '@ionic/react/css/typography.css';
/* Optional CSS utils that can be commented out */
import '@ionic/react/css/display.css';
import '@ionic/react/css/flex-utils.css';
import '@ionic/react/css/float-elements.css';
import '@ionic/react/css/padding.css';
import '@ionic/react/css/text-alignment.css';
import '@ionic/react/css/text-transformation.css';
/**
* Ionic Dark Mode
* -----------------------------------------------------
* For more info, please see:
* https://ionicframework.com/docs/theming/dark-mode
*/
// import "@ionic/react/css/palettes/dark.always.css";
// import "@ionic/react/css/palettes/dark.system.css";
import '@ionic/react/css/palettes/dark.class.css';
/* Theme variables */
import './theme/variables.css';
/* Global styles */
import './App.scss';
import RedirectToLogin from './components/RedirectToLogin';
import { AppContext, AppContextProvider } from './data/AppContext';
import { connect } from './data/connect';
import { loadConfData } from './data/sessions/sessions.actions';
import { loadUserData, setIsLoggedIn, setUsername } from './data/user/user.actions';
import { Schedule } from './models/Schedule';
import Account from './pages/Account';
import Login from './pages/Login';
import MainTabs from './pages/MainTabs';
import Signup from './pages/Signup';
import Support from './pages/Support';
import Tutorial from './pages/Tutorial';
//
import { Redirect } from 'react-router';
import { AccountPage } from './pages/SBAccount';
import LoginPage from './pages/SBLogin';
//
import SBLogout from './pages/SBLogout';
import StartupLoading from './pages/debug/StartupLoading';
import WelcomePage from './pages/debug/WelcomePage';
import Helloworld from './pages/debug/helloworld';
//
import SBLoginError from './SBLoginError';
import './i18n';
import UnlockMemberShip from './pages/UnlockMembership';
import EventDetail from './pages/event_detail';
//
// A wrapper for <Route> that redirects to the login
// screen if you're not yet authenticated.
function PrivateRoute({ children, ...rest }) {
const { session } = useContext(AppContext);
return <Route {...rest} render={({ location }) => (session ? children : <Redirect to="/sblogin" />)} />;
}
setupIonicReact();
const App: React.FC = () => {
return (
<AppContextProvider>
<IonicAppConnected />
</AppContextProvider>
);
};
interface StateProps {
darkMode: boolean;
schedule: Schedule;
}
interface DispatchProps {
loadConfData: typeof loadConfData;
loadUserData: typeof loadUserData;
setIsLoggedIn: typeof setIsLoggedIn;
setUsername: typeof setUsername;
}
interface IonicAppProps extends StateProps, DispatchProps {}
function AppOutlet() {
return (
<IonRouterOutlet id="main">
{/*
We use IonRoute here to keep the tabs state intact,
which makes transitions between tabs and non tab pages smooth
*/}
{/* <Route path="/tabs" render={() => <MainTabs />} /> */}
<Route path="/account" component={Account} />
<Route path="/login" component={Login} />
<Route path="/signup" component={Signup} />
<Route path="/support" component={Support} />
<Route path="/tutorial" component={Tutorial} />
<Route path="/login_error" component={SBLoginError} />
<Route
path="/logout"
render={() => {
return <RedirectToLogin setIsLoggedIn={setIsLoggedIn} setUsername={setUsername} />;
}}
/>
<Route path="/debug">
<Route path="/debug/helloworld" component={Helloworld} />
<Route path="/debug/StartupLoading" component={StartupLoading} />
<Route path="/debug/WelcomePage" component={WelcomePage} />
</Route>
<Route path="/helloworld" component={Helloworld} />
<Route path="/event_detail/1" render={() => <EventDetail />} exact={true} />
{/* */}
<Route path="/privacy/en" render={() => <PrivacyPage />} exact={true} />
{/* nested route / cascade route example */}
<Route path="/tabs">
<MainTabs />
</Route>
<Route exact path="/unlock-membership" render={() => <UnlockMemberShip />} />
<Route exact path="/sblogout" render={() => <SBLogout />} />
<Route exact path="/sblogin" render={() => <LoginPage />} />
<PrivateRoute path="/sbaccount">
<AccountPage />
</PrivateRoute>
{/* <Route path="/" component={HomeOrTutorial} exact /> */}
<Route
exact
path="/"
render={() => <RedirectToLogin setIsLoggedIn={setIsLoggedIn} setUsername={setUsername} />}
/>
</IonRouterOutlet>
);
}
const IonicApp: React.FC<IonicAppProps> = ({
darkMode,
schedule,
setIsLoggedIn,
setUsername,
loadConfData,
loadUserData,
}) => {
useEffect(() => {
loadUserData();
loadConfData();
// eslint-disable-next-line
}, []);
return schedule.groups.length === 0 ? (
<div></div>
) : (
<IonApp className={`${darkMode ? 'ion-palette-dark' : ''}`}>
<IonReactRouter>
<IonSplitPane contentId="main">
{/* */}
<Menu />
{/* <AppOutlet /> */}
<IonNav root={() => <AppOutlet />}></IonNav>;
</IonSplitPane>
</IonReactRouter>
</IonApp>
);
// TODO: obsoleted, delete this
// return schedule.groups.length === 0 ? (
// <div></div>
// ) : (
// <IonApp className={`${darkMode ? 'ion-palette-dark' : ''}`}>
// <IonReactRouter>
// <IonSplitPane contentId="main">
// {/* */}
// <Menu />
// <IonRouterOutlet id="main">
// {/*
// We use IonRoute here to keep the tabs state intact,
// which makes transitions between tabs and non tab pages smooth
// */}
// {/* <Route path="/tabs" render={() => <MainTabs />} /> */}
// <Route path="/account" component={Account} />
// <Route path="/login" component={Login} />
// <Route path="/signup" component={Signup} />
// <Route path="/support" component={Support} />
// <Route path="/tutorial" component={Tutorial} />
// <Route
// path="/logout"
// render={() => {
// return <RedirectToLogin setIsLoggedIn={setIsLoggedIn} setUsername={setUsername} />;
// }}
// />
// <Route path="/debug">
// <Route path="/debug/helloworld" component={Helloworld} />
// <Route path="/debug/StartupLoading" component={StartupLoading} />
// <Route path="/debug/WelcomePage" component={WelcomePage} />
// </Route>
// <Route path="/helloworld" component={Helloworld} />
// <Route path="/event_detail/1" render={() => <EventDetail />} exact={true} />
// {/* nested route / cascade route example */}
// <Route path="/tabs">
// <MainTabs />
// </Route>
// <PrivateRoute path="/sbaccount">
// <AccountPage />
// </PrivateRoute>
// <Route
// path="/sblogout"
// render={() => {
// return <SBLogout />;
// }}
// />
// <Route
// exact
// path="/sblogin"
// render={() => {
// return <LoginPage />;
// }}
// />
// <Route path="/" component={HomeOrTutorial} exact />
// </IonRouterOutlet>
// </IonSplitPane>
// </IonReactRouter>
// </IonApp>
// );
};
export default App;
const IonicAppConnected = connect<{}, StateProps, DispatchProps>({
mapStateToProps: state => ({
darkMode: state.user.darkMode,
schedule: state.data.schedule,
}),
mapDispatchToProps: {
loadConfData,
loadUserData,
setIsLoggedIn,
setUsername,
},
component: IonicApp,
});

View File

@@ -1,5 +0,0 @@
const SBLoginError = () => {
return <>Login Error</>;
};
export default SBLoginError;

View File

@@ -1,280 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders without crashing 1`] = `
<DocumentFragment>
<ion-app>
<ion-split-pane
content-id="main"
>
<ion-menu
content-id="main"
>
<ion-header>
<ion-toolbar>
<ion-title>
Menu
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content
class="outer-content"
>
<ion-list>
<ion-list-header>
Navigate
</ion-list-header>
<ion-menu-toggle
auto-hide="false"
>
<ion-item>
<ion-icon
slot="start"
/>
<ion-label>
Schedule
</ion-label>
</ion-item>
</ion-menu-toggle>
<ion-menu-toggle
auto-hide="false"
>
<ion-item>
<ion-icon
slot="start"
/>
<ion-label>
Speakers
</ion-label>
</ion-item>
</ion-menu-toggle>
<ion-menu-toggle
auto-hide="false"
>
<ion-item>
<ion-icon
slot="start"
/>
<ion-label>
Map
</ion-label>
</ion-item>
</ion-menu-toggle>
<ion-menu-toggle
auto-hide="false"
>
<ion-item>
<ion-icon
slot="start"
/>
<ion-label>
About
</ion-label>
</ion-item>
</ion-menu-toggle>
</ion-list>
<ion-list>
<ion-list-header>
Account
</ion-list-header>
<ion-menu-toggle
auto-hide="false"
>
<ion-item>
<ion-icon
slot="start"
/>
<ion-label>
Account
</ion-label>
</ion-item>
</ion-menu-toggle>
<ion-menu-toggle
auto-hide="false"
>
<ion-item>
<ion-icon
slot="start"
/>
<ion-label>
Support
</ion-label>
</ion-item>
</ion-menu-toggle>
<ion-menu-toggle
auto-hide="false"
>
<ion-item>
<ion-icon
slot="start"
/>
<ion-label>
Logout
</ion-label>
</ion-item>
</ion-menu-toggle>
</ion-list>
<ion-list>
<ion-list-header>
Tutorial
</ion-list-header>
<ion-item>
<ion-icon
slot="start"
/>
Show Tutorial
</ion-item>
</ion-list>
</ion-content>
</ion-menu>
<ion-router-outlet
id="main"
>
<div
style="display: flex; position: absolute; top: 0px; left: 0px; right: 0px; bottom: 0px; flex-direction: column; width: 100%; height: 100%; contain: layout size style;"
>
<div
class="tabs-inner"
style="position: relative; flex: 1; contain: layout size style;"
>
<ion-router-outlet>
<div
class="ion-page ion-page-invisible"
>
<ion-header>
<ion-toolbar
color="primary"
>
<ion-buttons
slot="start"
>
<ion-menu-button />
</ion-buttons>
<ion-segment>
<ion-segment-button
value="all"
>
All
</ion-segment-button>
<ion-segment-button
value="favorites"
>
Favorites
</ion-segment-button>
</ion-segment>
<ion-buttons
slot="end"
>
<ion-button>
<ion-icon
slot="icon-only"
/>
</ion-button>
</ion-buttons>
</ion-toolbar>
<ion-toolbar
color="primary"
>
<ion-searchbar
placeholder="Search"
/>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-refresher
slot="fixed"
>
<ion-refresher-content />
</ion-refresher>
<ion-list>
<ion-list-header>
No Sessions Found
</ion-list-header>
</ion-list>
<ion-list
style="display: none;"
/>
</ion-content>
<ion-fab
horizontal="end"
slot="fixed"
vertical="bottom"
>
<ion-fab-button>
<ion-icon />
</ion-fab-button>
<ion-fab-list
side="top"
>
<ion-fab-button
color="vimeo"
>
<ion-icon />
</ion-fab-button>
<ion-fab-button
color="google"
>
<ion-icon />
</ion-fab-button>
<ion-fab-button
color="twitter"
>
<ion-icon />
</ion-fab-button>
<ion-fab-button
color="facebook"
>
<ion-icon />
</ion-fab-button>
</ion-fab-list>
</ion-fab>
</div>
</ion-router-outlet>
</div>
<ion-tab-bar
current-path="/tabs/schedule"
selected-tab="schedule"
slot="bottom"
>
<ion-tab-button
href="/tabs/schedule"
tab="schedule"
>
<ion-icon />
<ion-label>
Schedule
</ion-label>
</ion-tab-button>
<ion-tab-button
href="/tabs/speakers"
tab="speakers"
>
<ion-icon />
<ion-label>
Speakers
</ion-label>
</ion-tab-button>
<ion-tab-button
href="/tabs/map"
tab="map"
>
<ion-icon />
<ion-label>
Map
</ion-label>
</ion-tab-button>
<ion-tab-button
href="/tabs/about"
tab="about"
>
<ion-icon />
<ion-label>
About
</ion-label>
</ion-tab-button>
</ion-tab-bar>
</div>
</ion-router-outlet>
</ion-split-pane>
</ion-app>
</DocumentFragment>
`;

View File

@@ -1,35 +0,0 @@
import { IonItem, IonLabel, IonList } from '@ionic/react';
import React from 'react';
interface AboutPopoverProps {
dismiss: () => void;
}
const AboutPopover: React.FC<AboutPopoverProps> = ({ dismiss }) => {
const close = (url: string) => {
window.open(url, '_blank');
dismiss();
};
return (
<IonList>
<IonItem button onClick={() => close('https://ionicframework.com/docs')}>
<IonLabel>Learn Ionic</IonLabel>
</IonItem>
<IonItem button onClick={() => close('https://ionicframework.com/docs/react')}>
<IonLabel>Documentation</IonLabel>
</IonItem>
<IonItem button onClick={() => close('https://showcase.ionicframework.com')}>
<IonLabel>Showcase</IonLabel>
</IonItem>
<IonItem button onClick={() => close('https://github.com/ionic-team/ionic-framework')}>
<IonLabel>GitHub Repo</IonLabel>
</IonItem>
<IonItem button onClick={dismiss}>
<IonLabel>Support</IonLabel>
</IonItem>
</IonList>
);
};
export default AboutPopover;

View File

@@ -1,27 +0,0 @@
.avatar {
display: block;
margin: auto;
min-height: 150px;
}
.avatar .avatar_wrapper {
margin: 16px auto 16px;
border-radius: 50%;
overflow: hidden;
height: 150px;
aspect-ratio: 1;
background: var(--ion-color-step-50);
border: thick solid var(--ion-color-step-200);
}
.avatar .avatar_wrapper:hover {
cursor: pointer;
}
.avatar .avatar_wrapper ion-icon.no-avatar {
width: 100%;
height: 115%;
}
.avatar img {
display: block;
object-fit: cover;
width: 100%;
height: 100%;
}

View File

@@ -1,56 +0,0 @@
import { Camera, CameraResultType } from '@capacitor/camera';
import { IonIcon } from '@ionic/react';
import { person } from 'ionicons/icons';
import { useEffect, useState } from 'react';
import { supabase } from '../supabaseClient';
import './Avatar.css';
export function Avatar({ url, onUpload }: { url: string; onUpload: (e: any, file: string) => Promise<void> }) {
const [avatarUrl, setAvatarUrl] = useState<string | undefined>();
useEffect(() => {
if (url) {
downloadImage(url);
}
}, [url]);
const uploadAvatar = async () => {
try {
const photo = await Camera.getPhoto({
resultType: CameraResultType.DataUrl,
});
const file = await fetch(photo.dataUrl!)
.then(res => res.blob())
.then(blob => new File([blob], 'my-file', { type: `image/${photo.format}` }));
const fileName = `${Math.random()}-${new Date().getTime()}.${photo.format}`;
let { error: uploadError } = await supabase.storage.from('avatars').upload(fileName, file);
if (uploadError) {
throw uploadError;
}
onUpload(null, fileName);
} catch (error) {
console.log(error);
}
};
const downloadImage = async (path: string) => {
try {
const { data, error } = await supabase.storage.from('avatars').download(path);
if (error) {
throw error;
}
const url = URL.createObjectURL(data!);
setAvatarUrl(url);
} catch (error: any) {
console.log('Error downloading image: ', error.message);
}
};
return (
<div className="avatar">
<div className="avatar_wrapper" onClick={uploadAvatar}>
{avatarUrl ? <img src={avatarUrl} /> : <IonIcon icon={person} className="no-avatar" />}
</div>
</div>
);
}

View File

@@ -1,10 +0,0 @@
import { IonIcon } from '@ionic/react';
import { checkmarkDone, star } from 'ionicons/icons';
export const ChatBottomDetails = ({ message }) => (
<span className="chat-bottom-details" id={`chatTime_${message.id}`}>
<span>{message.date}</span>
{message.sent && <IonIcon icon={checkmarkDone} color="primary" style={{ fontSize: '0.8rem' }} />}
{message.starred && <IonIcon icon={star} />}
</span>
);

View File

@@ -1,73 +0,0 @@
import {
IonIcon,
IonItem,
IonItemOption,
IonItemOptions,
IonItemSliding,
IonNavLink,
IonText,
IonThumbnail,
} from '@ionic/react';
import { checkmarkDone } from 'ionicons/icons';
import ChatHelloworld from '../../pages/chat';
import { ContactStore } from '../../store';
import { getContacts } from '../../store/Selectors';
import HKPartyIonDeleteIcon from '../HKPartyIonDeleteIcon';
import './style.scss';
const ChatItem = ({ chat }) => {
const contacts = ContactStore.useState(getContacts);
const { chats, contact_id } = chat;
const { read, date, preview, received } = chats[chats.length - 1];
const contact = contacts.filter(c => c.id === contact_id)[0];
const notificationCount = chats.filter(chat => chat.read === false).length;
return (
<>
<IonItemSliding>
{/*
<IonItemOptions side="start">
<IonItemOption color="success">Archive</IonItemOption>
</IonItemOptions>
*/}
{/* */}
<IonNavLink routerDirection="forward" component={() => <ChatHelloworld />}>
<IonItem
className="chat-row"
// routerLink={`/tabs/messages/${contact.id}`}
lines="full"
detail={false}
>
<IonThumbnail slot="start" style={{ '--border-radius': '50%' }}>
<img alt="Silhouette of mountains" src="https://ionicframework.com/docs/img/demos/thumbnail.svg" />
</IonThumbnail>
<div className="chat-row-content">
<IonText>{contact.name}</IonText>
<IonText>{read && received && <IonIcon icon={checkmarkDone} color="primary" />}</IonText>
<IonText>{preview}</IonText>
</div>
<div slot="end">
<div>
<IonText>{date}</IonText>
<IonText>
{notificationCount > 0 && <IonText className="chat-notification">{notificationCount}</IonText>}
</IonText>
</div>
</div>
</IonItem>
</IonNavLink>
{/* */}
<IonItemOptions side="end">
<IonItemOption color="danger">
<HKPartyIonDeleteIcon size={'large'} />
</IonItemOption>
</IonItemOptions>
</IonItemSliding>
</>
);
};
export default ChatItem;

View File

@@ -1,20 +0,0 @@
.chat-row {
.chat-row-content {
padding: 1rem;
}
.chat-content {
background-color: pink;
}
// img {
// border-radius: 500px;
// height: 2.5rem;
// width: 2.5rem;
// margin-right: 1.5rem;
// }
// ion-label {
// h1 {
// font-size: 1rem;
// }
// }
}

View File

@@ -1,14 +0,0 @@
const Quote = ({ message, contact, repliedMessage }) => (
<div className="in-chat-reply-to-container">
<h1>{contact.name}</h1>
<p>{repliedMessage.preview}</p>
</div>
);
export const ChatRepliedQuote = ({ message, contact, repliedMessage }) => {
if (message.reply && repliedMessage) {
return <Quote message={message} contact={contact} repliedMessage={repliedMessage} />;
} else {
return '';
}
};

View File

@@ -1,52 +0,0 @@
import {
IonButton,
IonButtons,
IonContent,
IonHeader,
IonItem,
IonLabel,
IonList,
IonTitle,
IonToolbar,
} from '@ionic/react';
import { ContactStore } from '../store';
import { getContacts } from '../store/Selectors';
import './ContactModal.scss';
const ContactModal = ({ close }) => {
const contacts = ContactStore.useState(getContacts);
return (
<div style={{ height: '100%' }}>
<IonHeader>
<IonToolbar>
<IonTitle>New Chat</IonTitle>
<IonButtons slot="end">
<IonButton fill="clear" onClick={close}>
Cancel
</IonButton>
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent>
<IonList>
{contacts.map(contact => {
return (
<IonItem key={`contact_${contact.id}`} lines="full" className="contact-item">
<img src={contact.avatar} alt="contact avatar" />
<IonLabel>
<h1>{contact.name}</h1>
<p>Available</p>
</IonLabel>
</IonItem>
);
})}
</IonList>
</IonContent>
</div>
);
};
export default ContactModal;

View File

@@ -1,14 +0,0 @@
.contact-item {
img {
border-radius: 500px;
height: 2.5rem;
width: 2.5rem;
margin-right: 1.5rem;
}
ion-label {
h1 {
font-size: 1rem;
}
}
}

View File

@@ -1,8 +0,0 @@
import { IonIcon } from '@ionic/react';
import { trashOutline } from 'ionicons/icons';
const HKPartyIonDeleteIcon = ({ ...props }) => {
return <IonIcon icon={trashOutline} {...props} />;
};
export default HKPartyIonDeleteIcon;

View File

@@ -1,8 +0,0 @@
import { IonIcon } from '@ionic/react';
import { trashOutline } from 'ionicons/icons';
const HKPartyIonDeleteIcon = ({ ...props }) => {
return <IonIcon icon={trashOutline} {...props} />;
};
export default HKPartyIonDeleteIcon;

View File

@@ -1,13 +0,0 @@
import { IonHeader } from '@ionic/react';
const HKPartyIonHeader = ({ children, ...props }) => {
return (
<IonHeader translucent={true} className="ion-no-border" {...props}>
{/* */}
{children}
{/* */}
</IonHeader>
);
};
export default HKPartyIonHeader;

View File

@@ -1,13 +0,0 @@
import { IonPage } from '@ionic/react';
const HKPartyIonPage = ({ children, ...props }) => {
return (
<IonPage {...props}>
{/* */}
{children}
{/* */}
</IonPage>
);
};
export default HKPartyIonPage;

View File

@@ -1,28 +0,0 @@
import { IonToolbar } from '@ionic/react';
const HKPartyIonToolbar = ({ children, ...props }) => {
return (
<IonToolbar {...props}>
{/* */}
<div
style={{
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
color: 'black',
minHeight: '30px',
margin: '0 10px',
//
fontWeight: 'bold',
fontSize: '1.2rem',
}}
>
{children}
</div>
{/* */}
</IonToolbar>
);
};
export default HKPartyIonToolbar;

View File

@@ -1,18 +0,0 @@
import React from 'react';
import { Redirect } from 'react-router';
import { connect } from '../data/connect';
interface StateProps {
hasSeenTutorial: boolean;
}
const HomeOrTutorial: React.FC<StateProps> = ({ hasSeenTutorial }) => {
return hasSeenTutorial ? <Redirect to="/tabs/schedule" /> : <Redirect to="/tutorial" />;
};
export default connect<{}, StateProps, {}>({
mapStateToProps: state => ({
hasSeenTutorial: state.user.hasSeenTutorial,
}),
component: HomeOrTutorial,
});

View File

@@ -1,24 +0,0 @@
import { IonContent, IonPage, IonSpinner, IonText } from '@ionic/react';
function Loading() {
return (
<IonPage>
<IonContent fullscreen={true} className="ion-padding">
<div
style={{
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
}}
>
<IonSpinner name="dots"></IonSpinner>
<IonText>{'Loading'}</IonText>
</div>
</IonContent>
</IonPage>
);
}
export default Loading;

View File

@@ -1,52 +0,0 @@
import React, { useEffect, useRef } from 'react';
import { Location } from '../models/Location';
interface MapProps {
locations: Location[];
mapCenter: Location;
}
const Map: React.FC<MapProps> = ({ mapCenter, locations }) => {
const mapEle = useRef<HTMLDivElement>(null);
const map = useRef<google.maps.Map>();
useEffect(() => {
map.current = new google.maps.Map(mapEle.current, {
center: {
lat: mapCenter.lat,
lng: mapCenter.lng,
},
zoom: 16,
});
addMarkers();
google.maps.event.addListenerOnce(map.current, 'idle', () => {
if (mapEle.current) {
mapEle.current.classList.add('show-map');
}
});
function addMarkers() {
locations.forEach(markerData => {
let infoWindow = new google.maps.InfoWindow({
content: `<h5>${markerData.name}</h5>`,
});
let marker = new google.maps.Marker({
position: new google.maps.LatLng(markerData.lat, markerData.lng),
map: map.current!,
title: markerData.name,
});
marker.addListener('click', () => {
infoWindow.open(map.current!, marker);
});
});
}
}, [mapCenter, locations]);
return <div ref={mapEle} className="map-canvas"></div>;
};
export default Map;

View File

@@ -1,88 +0,0 @@
ion-menu ion-content {
--padding-top: 20px;
--padding-bottom: 20px;
--background: var(--ion-item-background, var(--ion-background-color, #fff));
}
/* Remove background transitions for switching themes */
ion-menu ion-item {
--transition: none;
}
ion-item.selected {
--color: var(--ion-color-primary);
}
/*
* Material Design Menu
*/
ion-menu.md ion-list {
padding: 20px 0;
}
ion-menu.md ion-list-header {
padding-left: 18px;
padding-right: 18px;
text-transform: uppercase;
letter-spacing: 0.1em;
font-size: min(0.875rem, 32px);
font-weight: 450;
}
ion-menu.md ion-item {
--padding-start: 18px;
margin-right: 10px;
border-radius: 0 50px 50px 0;
font-weight: 500;
}
ion-menu.md ion-item.selected {
--background: rgba(var(--ion-color-primary-rgb), 0.14);
}
ion-menu.md ion-item.selected ion-icon {
color: var(--ion-color-primary);
}
ion-menu.md ion-list-header,
ion-menu.md ion-item ion-icon {
color: var(--ion-color-step-650, #5f6368);
}
ion-menu.md ion-list:not(:last-of-type) {
border-bottom: 1px solid var(--ion-color-step-150, #d7d8da);
}
/*
* iOS Menu
*/
ion-menu.ios ion-list-header {
padding-left: 16px;
padding-right: 16px;
margin-bottom: 8px;
font-size: clamp(22px, 1.375rem, 40px);
}
ion-menu.ios ion-list {
padding: 20px 0 0;
}
ion-menu.ios ion-item {
--padding-start: 16px;
--min-height: 50px;
}
ion-menu.ios ion-item ion-icon {
font-size: 24px;
color: #73849a;
}
ion-menu.ios ion-item.selected ion-icon {
color: var(--ion-color-primary);
}

View File

@@ -1,138 +0,0 @@
import React from 'react';
import { RouteComponentProps, useLocation, withRouter } from 'react-router';
import {
IonContent,
IonIcon,
IonItem,
IonLabel,
IonList,
IonListHeader,
IonMenu,
IonMenuToggle,
IonToggle,
} from '@ionic/react';
import {
calendarOutline,
hammer,
help,
informationCircleOutline,
logIn,
logOut,
mapOutline,
moonOutline,
peopleOutline,
person,
personAdd,
} from 'ionicons/icons';
import { connect } from '../data/connect';
import { setDarkMode } from '../data/user/user.actions';
import './Menu.css';
const routes = {
appPages: [
{ title: 'Schedule', path: '/tabs/schedule', icon: calendarOutline },
{ title: 'Speakers', path: '/tabs/speakers', icon: peopleOutline },
{ title: 'Map', path: '/tabs/map', icon: mapOutline },
{ title: 'About', path: '/tabs/about', icon: informationCircleOutline },
{ title: 'Message', path: '/tabs/message', icon: informationCircleOutline },
{ title: 'Profile', path: '/tabs/profile', icon: informationCircleOutline },
],
loggedInPages: [
{ title: 'Account', path: '/account', icon: person },
{ title: 'Support', path: '/support', icon: help },
{ title: 'Logout', path: '/logout', icon: logOut },
],
loggedOutPages: [
{ title: 'Login', path: '/login', icon: logIn },
{ title: 'Support', path: '/support', icon: help },
{ title: 'Signup', path: '/signup', icon: personAdd },
],
};
interface Pages {
title: string;
path: string;
icon: string;
routerDirection?: string;
}
interface StateProps {
darkMode: boolean;
isAuthenticated: boolean;
menuEnabled: boolean;
}
interface DispatchProps {
setDarkMode: typeof setDarkMode;
}
interface MenuProps extends RouteComponentProps, StateProps, DispatchProps {}
const Menu: React.FC<MenuProps> = ({ darkMode, history, isAuthenticated, setDarkMode, menuEnabled }) => {
const location = useLocation();
function renderlistItems(list: Pages[]) {
return list
.filter(route => !!route.path)
.map(p => (
<IonMenuToggle key={p.title} auto-hide="false">
<IonItem
detail={false}
routerLink={p.path}
routerDirection="none"
className={location.pathname.startsWith(p.path) ? 'selected' : undefined}
>
<IonIcon slot="start" icon={p.icon} />
<IonLabel>{p.title}</IonLabel>
</IonItem>
</IonMenuToggle>
));
}
return (
<IonMenu type="overlay" disabled={!menuEnabled} contentId="main">
<IonContent forceOverscroll={false}>
<IonList lines="none">
<IonListHeader>Conference</IonListHeader>
{renderlistItems(routes.appPages)}
</IonList>
<IonList lines="none">
<IonListHeader>Account</IonListHeader>
{isAuthenticated ? renderlistItems(routes.loggedInPages) : renderlistItems(routes.loggedOutPages)}
<IonItem>
<IonIcon slot="start" icon={moonOutline} aria-hidden="true"></IonIcon>
<IonToggle checked={darkMode} onClick={() => setDarkMode(!darkMode)}>
Dark Mode
</IonToggle>
</IonItem>
</IonList>
<IonList lines="none">
<IonListHeader>Tutorial</IonListHeader>
<IonItem
button
onClick={() => {
history.push('/tutorial');
}}
>
<IonIcon slot="start" icon={hammer} />
<IonLabel>Show Tutorial</IonLabel>
</IonItem>
</IonList>
</IonContent>
</IonMenu>
);
};
export default connect<{}, StateProps, {}>({
mapStateToProps: state => ({
darkMode: state.user.darkMode,
isAuthenticated: state.user.isLoggedin,
menuEnabled: state.data.menuEnabled,
}),
mapDispatchToProps: {
setDarkMode,
},
component: withRouter(Menu),
});

View File

@@ -1,23 +0,0 @@
import { IonRouterContext } from '@ionic/react';
import React, { useContext, useEffect } from 'react';
interface RedirectToLoginProps {
setIsLoggedIn: Function;
setUsername: Function;
}
const RedirectToLogin: React.FC<RedirectToLoginProps> = ({ setIsLoggedIn, setUsername }) => {
const ionRouterContext = useContext(IonRouterContext);
useEffect(() => {
setIsLoggedIn(false);
setUsername(undefined);
ionRouterContext.push('/tabs/schedule');
console.error('who call this ?');
}, [setIsLoggedIn, setUsername]);
return null;
};
export default RedirectToLogin;

View File

@@ -1,54 +0,0 @@
import { CreateAnimation, IonButton, IonCol, IonIcon, IonLabel, IonRow } from '@ionic/react';
import { closeCircleOutline } from 'ionicons/icons';
import { useEffect, useState } from 'react';
// import './style.css';
const ReplyTo = ({ contact, replyToMessage = false, replyToAnimationRef, setReplyToMessage, messageSent }) => {
const [cancellingReplyTo, setCancellingReplyTo] = useState(false);
useEffect(() => {
messageSent && cancelReplyTo();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [messageSent]);
const slideAnimation = {
property: 'transform',
fromValue: 'translateY(100px)',
toValue: 'translateY(0px)',
};
const replyToAnimation = {
duration: 300,
direction: !cancellingReplyTo ? 'normal' : 'reverse',
iterations: '1',
fromTo: [slideAnimation],
easing: 'ease-in-out',
};
// Cancel the reply-to
const cancelReplyTo = async () => {
setCancellingReplyTo(true);
await replyToAnimationRef.current.animation.play();
setCancellingReplyTo(false);
setReplyToMessage(false);
};
return (
<CreateAnimation ref={replyToAnimationRef} {...replyToAnimation}>
<IonRow className="ion-align-items-center chat-reply-to-row" id="replyTo">
<IonCol size="10" className="chat-reply-to-container">
<IonLabel className="chat-reply-to-name">{contact}</IonLabel>
<IonLabel className="chat-reply-to-message">{replyToMessage.preview}</IonLabel>
</IonCol>
<IonCol size="1">
<IonButton fill="clear" onClick={cancelReplyTo}>
<IonIcon size="large" icon={closeCircleOutline} color="primary" />
</IonButton>
</IonCol>
</IonRow>
</CreateAnimation>
);
};
export default ReplyTo;

View File

@@ -1,290 +0,0 @@
.chat-page ion-header,
.chat-page ion-toolbar {
--min-height: 3.5rem;
}
.chat-page ion-title {
margin-left: -3.5rem;
}
.chat-page ion-title p {
padding: 0;
margin: 0;
}
.chat-contact {
display: flex;
flex-direction: row;
align-content: center;
justify-content: center;
align-items: center;
}
.chat-contact img {
height: 2rem;
width: 2rem;
border-radius: 500px;
}
.chat-contact-details {
display: flex;
flex-direction: column;
margin-left: 0.5rem;
text-align: left;
}
.chat-contact-details p {
font-size: 0.9rem;
}
.chat-contact-details ion-text {
font-size: 0.7rem;
font-weight: 400;
}
.chat-bubble {
border-radius: 5px;
margin-left: 1rem;
margin-right: 1rem;
margin-top: 0.8rem;
padding: 0.5rem;
max-width: 80%;
clear: both;
display: flex;
flex-direction: row;
transition: 0.2s all linear;
}
.chat-bubble:last-child {
margin-bottom: 0.8rem;
}
.bubble-sent {
background-color: var(--chat-bubble-sent-color);
float: right;
}
.bubble-received {
background-color: var(--chat-bubble-received-color);
float: left;
}
.chat-bubble p {
padding: 0;
margin: 0;
}
.chat-footer {
/* background-color: rgb(22, 22, 22); */
border-top: 1px solid rgb(47, 47, 47);
padding-top: 0.2rem;
padding-bottom: 1rem;
}
.chat-footer ion-textarea {
/* background-color: rgb(31, 31, 31); */
background-color: rgba(32, 32, 32, 0.1);
/* border: 1px solid rgb(36, 36, 36); */
color: white;
border-radius: 25px;
padding-left: 0.5rem;
caret-color: var(--ion-color-primary);
}
.chat-footer ion-icon {
font-size: 1.5rem;
margin-top: 0.2rem;
}
.chat-input-container {
width: 70%;
margin-right: 0.75rem;
}
.chat-send-button {
margin: 0 !important;
padding: 0 !important;
position: absolute;
right: 17px;
margin-top: -0.2rem !important;
display: flex;
flex-direction: row;
align-content: center;
align-items: center;
justify-content: center;
}
.chat-send-button ion-icon {
color: white;
background-color: var(--ion-color-primary);
font-size: 1.1rem;
border-radius: 500px;
padding: 0.5rem;
}
.chat-time {
color: rgb(165, 165, 165);
font-size: 0.75rem;
right: 0;
bottom: 0 !important;
margin: 0;
padding: 0;
margin-top: 5px;
}
.bubble-arrow {
position: absolute;
float: left;
left: 6px;
margin-top: -8px;
/* top: 0px; */
}
.bubble-arrow.alt {
position: relative;
bottom: 0px;
left: auto;
right: -3px;
float: right;
}
.bubble-arrow:after {
content: "";
position: absolute;
border-top: 15px solid var(--chat-bubble-received-color);
border-left: 15px solid transparent;
border-radius: 4px 0 0 0px;
width: 0;
height: 0;
}
.bubble-arrow.alt:after {
border-top: 15px solid var(--chat-bubble-sent-color);
transform: scaleX(-1);
}
.chat-reply-to-row {
bottom: 70px !important;
position: absolute;
border-left: 4px solid rgb(224, 176, 18);
width: 100%;
background-color: rgb(22, 22, 22);
border-top: 1px solid rgb(47, 47, 47);
padding: 0.5rem;
padding-bottom: 0.8rem;
}
.chat-reply-to-container {
display: flex;
flex-direction: column;
}
.chat-reply-to-name {
color: rgb(224, 176, 18);
font-weight: 500;
margin-bottom: 0.5rem;
}
.chat-reply-to-message {
font-size: 0.8rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.all-chats {
}
.chat-bottom-details {
display: flex;
flex-direction: row;
width: 100%;
align-content: center;
align-items: center;
justify-content: flex-end;
margin-top: 0.4rem;
}
.chat-bottom-details ion-icon {
font-size: 0.6rem;
color: grey;
margin-left: 0.5rem;
margin-top: 0.05rem;
}
.chat-bottom-details span {
margin: 0;
padding: 0;
font-size: 0.75rem;
color: rgb(190, 190, 190);
}
.in-chat-reply-to-container {
/* background-color: rgba(0, 0, 0, 0.2); */
border-left: 3px solid rgb(224, 176, 18);
height: fit-content;
padding: 0.5rem;
border-radius: 5px;
margin-bottom: 0.5rem;
}
.in-chat-reply-to-container h1 {
margin: 0;
padding: 0;
color: rgb(224, 176, 18);
font-size: 0.8rem;
}
.in-chat-reply-to-container p {
color: rgb(167, 167, 167);
font-size: 0.8rem;
}
.bottom-container {
position: absolute;
bottom: 4.5rem;
height: 5rem;
background-color: red;
width: 100%;
}

View File

@@ -1,102 +0,0 @@
import { AlertButton, IonAlert, IonItemDivider, IonItemGroup, IonLabel, IonList, IonListHeader } from '@ionic/react';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { connect } from '../data/connect';
import { addFavorite, removeFavorite } from '../data/sessions/sessions.actions';
import { Schedule, Session } from '../models/Schedule';
import SessionListItem from './SessionListItem';
interface OwnProps {
schedule: Schedule;
listType: 'all' | 'favorites';
hide: boolean;
}
interface StateProps {
favoriteSessions: number[];
}
interface DispatchProps {
addFavorite: typeof addFavorite;
removeFavorite: typeof removeFavorite;
}
interface SessionListProps extends OwnProps, StateProps, DispatchProps {}
const SessionList: React.FC<SessionListProps> = ({
addFavorite,
removeFavorite,
favoriteSessions,
hide,
schedule,
listType,
}) => {
const scheduleListRef = useRef<HTMLIonListElement>(null);
const [showAlert, setShowAlert] = useState(false);
const [alertHeader, setAlertHeader] = useState('');
const [alertMessage, setAlertMessage] = useState('');
const [alertButtons, setAlertButtons] = useState<(AlertButton | string)[]>([]);
const handleShowAlert = useCallback((header: string, message: string, buttons: AlertButton[]) => {
setAlertHeader(header);
setAlertMessage(message);
setAlertButtons(buttons);
setShowAlert(true);
}, []);
useEffect(() => {
if (scheduleListRef.current) {
scheduleListRef.current.closeSlidingItems();
}
}, [hide]);
if (schedule.groups.length === 0 && !hide) {
return (
<IonList>
<IonListHeader>No Sessions Found</IonListHeader>
</IonList>
);
}
return (
<>
<IonList ref={scheduleListRef} style={hide ? { display: 'none' } : {}}>
{schedule.groups.map((group, index: number) => (
<IonItemGroup key={`group-${index}`}>
<IonItemDivider sticky>
<IonLabel>{group.time}</IonLabel>
</IonItemDivider>
{group.sessions.map((session: Session, sessionIndex: number) => (
<SessionListItem
onShowAlert={handleShowAlert}
isFavorite={favoriteSessions.indexOf(session.id) > -1}
onAddFavorite={addFavorite}
onRemoveFavorite={removeFavorite}
key={`group-${index}-${sessionIndex}`}
session={session}
listType={listType}
/>
))}
</IonItemGroup>
))}
</IonList>
<IonAlert
isOpen={showAlert}
header={alertHeader}
message={alertMessage}
buttons={alertButtons}
onDidDismiss={() => setShowAlert(false)}
></IonAlert>
</>
);
};
export default connect<OwnProps, StateProps, DispatchProps>({
mapStateToProps: state => ({
favoriteSessions: state.data.favorites,
}),
mapDispatchToProps: {
addFavorite,
removeFavorite,
},
component: SessionList,
});

View File

@@ -1,31 +0,0 @@
/*
* Material Design
*/
.md .session-list-filter ion-toolbar ion-button {
text-transform: capitalize;
letter-spacing: 0;
}
.md .session-list-filter ion-checkbox {
--checkbox-background-checked: transparent;
--border-color: transparent;
--border-color-checked: transparent;
--checkmark-color: var(--ion-color-primary);
}
.md .session-list-filter ion-list {
background: inherit;
}
/*
* iOS
*/
.ios .session-list-filter ion-list-header {
margin-top: 10px;
}
.ios .session-list-filter ion-checkbox {
color: var(--ion-color-primary);
}

View File

@@ -1,152 +0,0 @@
import React from 'react';
import { getMode } from '@ionic/core';
import {
IonButton,
IonButtons,
IonCheckbox,
IonContent,
IonFooter,
IonHeader,
IonIcon,
IonItem,
IonList,
IonListHeader,
IonTitle,
IonToolbar,
} from '@ionic/react';
import {
call,
cog,
colorPalette,
compass,
construct,
document,
hammer,
logoAngular,
logoIonic,
restaurant,
} from 'ionicons/icons';
import './SessionListFilter.css';
import { connect } from '../data/connect';
import { updateFilteredTracks } from '../data/sessions/sessions.actions';
interface OwnProps {
onDismissModal: () => void;
}
interface StateProps {
allTracks: string[];
filteredTracks: string[];
}
interface DispatchProps {
updateFilteredTracks: typeof updateFilteredTracks;
}
type SessionListFilterProps = OwnProps & StateProps & DispatchProps;
const SessionListFilter: React.FC<SessionListFilterProps> = ({
allTracks,
filteredTracks,
onDismissModal,
updateFilteredTracks,
}) => {
const ios = getMode() === 'ios';
const toggleTrackFilter = (track: string) => {
if (filteredTracks.indexOf(track) > -1) {
updateFilteredTracks(filteredTracks.filter(x => x !== track));
} else {
updateFilteredTracks([...filteredTracks, track]);
}
};
const handleDeselectAll = () => {
updateFilteredTracks([]);
};
const handleSelectAll = () => {
updateFilteredTracks([...allTracks]);
};
const iconMap: { [key: string]: any } = {
Angular: logoAngular,
Documentation: document,
Food: restaurant,
Ionic: logoIonic,
Tooling: hammer,
Design: colorPalette,
Services: cog,
Workshop: construct,
Navigation: compass,
Communication: call,
};
return (
<>
<IonHeader translucent={true} className="session-list-filter">
<IonToolbar>
<IonButtons slot="start">
{ios && <IonButton onClick={onDismissModal}>Cancel</IonButton>}
{!ios && <IonButton onClick={handleDeselectAll}>Reset</IonButton>}
</IonButtons>
<IonTitle>Filter Sessions</IonTitle>
<IonButtons slot="end">
<IonButton onClick={onDismissModal} strong>
Done
</IonButton>
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent className="session-list-filter">
<IonList lines={ios ? 'inset' : 'full'}>
<IonListHeader>Tracks</IonListHeader>
{allTracks.map(track => (
<IonItem key={track}>
{ios && <IonIcon slot="start" icon={iconMap[track]} color="medium" aria-hidden="true" />}
<IonCheckbox
onIonChange={() => toggleTrackFilter(track)}
checked={filteredTracks.indexOf(track) !== -1}
color="primary"
value={track}
>
{track}
</IonCheckbox>
</IonItem>
))}
</IonList>
</IonContent>
{ios && (
<IonFooter>
<IonToolbar>
<IonButtons slot="start">
<IonButton onClick={handleDeselectAll}>Deselect All</IonButton>
</IonButtons>
<IonButtons slot="end">
<IonButton onClick={handleSelectAll}>Select All</IonButton>
</IonButtons>
</IonToolbar>
</IonFooter>
)}
</>
);
};
export default connect<OwnProps, StateProps, DispatchProps>({
mapStateToProps: state => ({
allTracks: state.data.allTracks,
filteredTracks: state.data.filteredTracks,
}),
mapDispatchToProps: {
updateFilteredTracks,
},
component: SessionListFilter,
});

Some files were not shown because too many files have changed in this diff Show More