├── API.RU.md
├── API.md
├── LICENSE
├── README.RU.md
├── README.md
└── Source
├── Android
├── .idea
│ ├── .gitignore
│ ├── assetWizardSettings.xml
│ ├── compiler.xml
│ ├── gradle.xml
│ └── misc.xml
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── r57zone
│ │ │ └── easynotes
│ │ │ └── ExampleInstrumentedTest.kt
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── assets
│ │ │ └── ReadMe.txt
│ │ ├── ic_launcher-playstore.png
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── r57zone
│ │ │ │ └── easynotes
│ │ │ │ └── MainActivity.kt
│ │ └── res
│ │ │ ├── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ │ ├── drawable
│ │ │ └── ic_launcher_background.xml
│ │ │ ├── icon.png
│ │ │ ├── layout
│ │ │ └── activity_main.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher_foreground.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher_foreground.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher_foreground.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher_foreground.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher_foreground.png
│ │ │ ├── values-night
│ │ │ └── themes.xml
│ │ │ ├── values
│ │ │ ├── colors.xml
│ │ │ ├── ic_launcher_background.xml
│ │ │ ├── strings.xml
│ │ │ └── themes.xml
│ │ │ └── xml
│ │ │ ├── backup_rules.xml
│ │ │ └── data_extraction_rules.xml
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── r57zone
│ │ └── easynotes
│ │ └── ExampleUnitTest.kt
├── build.gradle
├── clear.bat
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
├── Multi
├── any.css
├── app.manifest
├── icons
│ ├── icon-114.png
│ ├── icon-120.png
│ ├── icon-144.png
│ ├── icon-152.png
│ ├── icon-180.png
│ ├── icon-72.png
│ ├── icon-76.png
│ └── icon.png
├── images
│ ├── back.png
│ ├── close.png
│ ├── done.png
│ ├── flashlight.png
│ ├── folders.png
│ ├── new.png
│ ├── qr.png
│ ├── rm.png
│ ├── search.png
│ ├── settings.png
│ ├── share.png
│ └── sync.png
├── index.html
├── ios.css
├── langs.js
├── manifest.json
├── pwa.js
├── style.css
└── windows.css
├── Web
├── ReadMe.txt
├── api
│ ├── .htaccess
│ ├── actions.php
│ ├── auth.php
│ ├── config.php
│ ├── notes.php
│ ├── received.php
│ └── syncnotes.php
├── cachemanifest.php
└── getnotes.php
└── Windows
├── AllowedIPs.txt
├── LangFile.pas
├── Languages
├── Arabic.txt
├── Chinese.txt
├── English.txt
├── French.txt
├── German.txt
├── Italian.txt
├── Japanese.txt
├── Korean.txt
├── Portuguese.txt
├── Russian.txt
└── Spanish.txt
├── Project1.dpr
├── Project1.dproj
├── Project1.res
├── Project1_Icon.ico
├── SQLite3.pas
├── SQLite3Utils.pas
├── SQLite3Wrap.pas
├── UI
├── darktheme.css
├── images
│ ├── done.png
│ ├── folders.png
│ ├── new.png
│ ├── rm.png
│ ├── search.png
│ └── settings.png
└── main.html
├── Unit1.dfm
├── Unit1.pas
├── Unit2.dfm
├── Unit2.pas
├── clear.bat
└── webapp
└── ReadMe.txt
/API.RU.md:
--------------------------------------------------------------------------------
1 | ## Easy Notes API
2 | Приложение для Windows является сервером заметок. Данные пересылаются в XML разметке. Текст заметки конвертируется в последовательность символов - "x" + номер символа. Например, слово "Привет" конвертируется в "x1055x1088x1080x1074x1077x1090".
3 |
4 | | Запрос | Тип запроса | Описание | Значение / Статус |
5 | | ------------- | ------------- | ------------- | ------------- |
6 | | `IP:PORT/api/connecttest` | GET | Получение статуса доступности сервера. | "ok" |
7 | | `IP:PORT/api/auth?id=DEVICE` | GET | Запрос на добавление в список авторизованных устройств. | "auth:ok" или "auth:denied" |
8 | | `IP:PORT/api/notes?id=DEVICE` | GET | Получение списка с идентификаторами (Unix timestamp), заметками и временем заметок (Unix timestamp с UTC смещением). | <notes> <note id="1553285632" datetime="1553300032">x72x101x108x108x111</note> <note id="1553248570" datetime="1553262970">x72x101x108x108x111</note> </notes> |
9 | | `IP:PORT/api/actions?id=DEVICE` | GET | Получение новых изменений от сервера. | <actions> <insert id="1553285632" datetime="1553300032">x72x101x108x108x111</insert> <update id="1553248570" datetime="1553262970">x72x101x108x108x111</update> <delete id="1553248570"></delete> </actions> |
10 | | `IP:PORT/api/received?id=DEVICE` | GET | Подтверждение получения новых изменений от сервера. | "ok" или "auth:denied" |
11 | | `IP:PORT/api/syncnotes?id=DEVICE` | POST | Отправка новых изменений от клиента. | <actions> <insert id="1553285632" datetime="1553300032">x72x101x108x108x111</insert> <update id="1553248570" datetime="1553262970">x72x101x108x108x111</update> <delete id="1553248570"></delete> </actions> |
12 |
13 | `IP` это адрес, с запущенным приложением для Windows. Порт по умолчанию 735. `DEVICE` это название устройства, например, `Android_g9N1z5S2` или `iOS_rM5s3Gz7`.
--------------------------------------------------------------------------------
/API.md:
--------------------------------------------------------------------------------
1 | ## Easy Notes API
2 | The Windows app is a notes server. The data is sent in XML markup. The text of the note is converted into a sequence of characters - "x" + character number. For example, the word "Hello" is converted to "x72x101x108x108x111".
3 |
4 | | Request | Request type | Description | Value / Status |
5 | | ------------- | ------------- | ------------- | ------------- |
6 | | `IP:PORT/api/connecttest` | GET | Getting the server availability status. | "ok" |
7 | | `IP:PORT/api/auth?id=DEVICE` | GET | Request to add to the list of authorized devices. | "auth:ok" or "auth:denied" |
8 | | `IP:PORT/api/notes?id=DEVICE` | GET | Getting a list with identifiers (Unix timestamp), notes and note times (Unix timestamp with UTC offset). | <notes> <note id="1553285632" datetime="1553300032">x72x101x108x108x111</note> <note id="1553248570" datetime="1553262970">x72x101x108x108x111</note> </notes> |
9 | | `IP:PORT/api/actions?id=DEVICE` | GET | Receiving new changes from the server. | <actions> <insert id="1553285632" datetime="1553300032">x72x101x108x108x111</insert> <update id="1553248570" datetime="1553262970">x72x101x108x108x111</update> <delete id="1553248570"></delete> </actions> |
10 | | `IP:PORT/api/received?id=DEVICE` | GET | Confirmation of receiving new changes from the server. | "ok" or "auth:denied" |
11 | | `IP:PORT/api/syncnotes?id=DEVICE` | POST | Sending new changes from the client. | <actions> <insert id="1553285632" datetime="1553300032">x72x101x108x108x111</insert> <update id="1553248570" datetime="1553262970">x72x101x108x108x111</update> <delete id="1553248570"></delete> </actions> |
12 |
13 | `IP` is the address running the application for Windows. The default port is 735. `DEVICE` is the name of the device, for example `Android_g9N1z5S2` or `iOS_rM5s3Gz7`.
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | English:
2 | The software, developed technologies and ideas belong to the author and are protected by copyright.
3 | The software can be used, distributed, and modified in the original source repository, but for everything else the author's permission is required.
4 |
5 | Russian:
6 | Программное обеспечение, разработанные технологии и идеи принадлежат автору и защищены авторским правом.
7 | Программное обеспечение можно использовать, распространять, вносить изменения в оригинальный репозиторий источник, но для всего остального необходимо разрешение автора.
8 |
9 | Chinese (Simplified):
10 | 软件、开发的技术和理念均归作者所有,并受版权保护。
11 | 软件可以在原始源代码库中使用、分发和修改,但对于其他用途,必须获得作者的许可。
12 |
13 | Spanish:
14 | El software, las tecnologías desarrolladas y las ideas pertenecen al autor y están protegidas por derechos de autor.
15 | El software puede usarse, distribuirse y modificarse en el repositorio fuente original, pero para cualquier otro uso se requiere el permiso del autor.
16 |
17 | Portuguese (Brazilian Portuguese):
18 | O software, as tecnologias desenvolvidas e as ideias pertencem ao autor e estão protegidos por direitos autorais.
19 | O software pode ser usado, distribuído e modificado no repositório de origem original, mas para qualquer outra finalidade é necessário obter a permissão do autor.
20 |
21 | French:
22 | Le logiciel, les technologies développées et les idées appartiennent à l'auteur et sont protégés par le droit d'auteur.
23 | Le logiciel peut être utilisé, distribué et modifié dans le dépôt source original, mais pour tout autre usage, l'autorisation de l'auteur est requise.
24 |
25 | German:
26 | Die Software, die entwickelten Technologien und Ideen gehören dem Autor und sind urheberrechtlich geschützt.
27 | Die Software kann im ursprünglichen Quellcode-Repository verwendet, verteilt und modifiziert werden, aber für alles andere ist die Erlaubnis des Autors erforderlich.
28 |
29 | Japanese:
30 | このソフトウェア、開発された技術、およびアイデアは著者に帰属し、著作権で保護されています。
31 | ソフトウェアは元のソースリポジトリ内で使用、配布、変更できますが、それ以外の用途には著者の許可が必要です。
32 |
33 | Arabic:
34 | البرنامج، والتقنيات المطورة، والأفكار تنتمي إلى المؤلف وهي محمية بموجب حقوق الطبع والنشر.
35 | يمكن استخدام البرنامج وتوزيعه وتعديله في مستودع المصدر الأصلي، ولكن يتطلب أي استخدام آخر إذن المؤلف.
36 |
37 | Italian:
38 | Il software, le tecnologie sviluppate e le idee appartengono all'autore e sono protetti da copyright.
39 | Il software può essere utilizzato, distribuito e modificato nel repository di origine originale, ma per tutto il resto è necessario il permesso dell'autore.
40 |
41 | Korean:
42 | 소프트웨어, 개발된 기술 및 아이디어는 저자에게 속하며 저작권으로 보호됩니다.
43 | 소프트웨어는 원본 소스 저장소에서 사용, 배포 및 수정할 수 있지만, 다른 모든 용도에는 저자의 허가가 필요합니다.
--------------------------------------------------------------------------------
/README.RU.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/r57zone/EasyNotes/)
2 | [](https://github.com/r57zone/EasyNotes/blob/master/README.RU.md)
3 | # EasyNotes
4 | 
5 |
6 | Простые заметки для Windows, Android и iOS, с прямой локальной синхронизацией или синхронизацией с веб-сервером. Сервером может выступать как приложение для Windows (для синхронизации необходимо запускать его), так и ваш веб-сервер. Посмотреть API можно [здесь](https://github.com/r57zone/EasyNotes/blob/master/API.RU.md).
7 |
8 | ## Особенности
9 | Поддерживаются следующие языки: английский, русский, китайский (традиционный), испанский, португальский (бразильский португальский), французкий, немецкий, японский, арабский, итальянский и корейский.
10 |
11 | 
12 | 
13 | 
14 | 
15 | 
16 | 
17 | 
18 | 
19 | 
20 | 
21 | 
22 | 
23 | 
24 | 
25 |
26 |
27 | Приложения имеют тёмную тему и автоматическое переключение на неё в тёмное время суток.
28 |
29 |
30 | Присутствует полная поддержка планшетов.
31 |
32 |
33 | Если необходимо оставить старую дату, при редактировани заметки, то на мобильных телефонах нужно нажать на дату, а на ПК зажать клавишу `Shift`, при нажатии на кнопку готово.
34 |
35 |
36 | Имеется ограничение на 5 мегабайт для заметок (кроме ПК), следить за объёмом доступной памяти можно в настройках приложения.
37 |
38 | ## Настройка
39 | ### Windows
40 | Для Windows есть 2 приложения, одно является серверным приложением, с которым синхронизируются другие клиентские приложения, а второе клиентским, которое синхронизируется с серверным приложением или веб-сервером.
41 |
42 | ### Android
43 | Установите `EasyNotes.apk`, выберите автопоиск IP адреса или введите зарезервированный постоянный IP вашего компьютера (об этом ниже). Если ваш маршрутизатор присваивает следующие IP адреса: `192.168.0.0/15`, `192.168.0.100/115`, `192.168.1.0/15`, `192.168.1.100/115`, `192.168.2.0/15`, `192.168.3.0/15`, то можно просто включить автопоиск IP адреса и приложение само найдет ваш компьютер.
44 |
45 | ### iOS 13+
46 | Если вы хотите синхронизироваться напрямую с ПК или http веб-сервером, то вам необходимо проделать следующее:
47 | 1. Загрузите архив "EasyNotes.iOS.zip", распакуйте его в папку EasyNotes и разместите папку в [Apple iCloud](https://www.icloud.com/iclouddrive/), также создайте папку `images` и переместите туда изображения из `EasyNotes\images`.
48 | 2. Установите приложение [HTML Viewer Q](https://apps.apple.com/us/app/html-viewer-q/id810042973) (или любое другое, способное отобразить HTML приложение и разрешающее интернет-соединения).
49 | 3. Запустите приложение `HTML Viewer Q`, нажмите иконку файлы (5-ая внизу). Нажмите `Обзор`, перейдите в iCloud Drive, далее в `Приложения` и нажмите на папке `EasyNotes` переместить, после чего переместите папку в `iPhone/HTML Viewer`.
50 | 4. Далее открываем `index.html`, закрываем приложение `HTML Viewer Q` и открываем его снова, после чего приложение заработает и все стили будут отображаться.
51 | 5. В настройках приложения можно отключить `Tabbed Browsing`, чтобы отключить верхний бар, с переключением HTML страниц.
52 |
53 |
54 | Если вы хотите просто использовать приложение без синхронизации или хотите синхронизироваться с https веб-сервером, то вам необходимо проделать следующее:
55 | 1. Откройте браузер Safari, на мобильном устройстве и введите там `https://easynotespwa.github.io`.
56 | 2. Нажмите кнопку `Поделиться` → `На экран Домой`. На рабочем столе появится ярлык для EasyNotes.
57 |
58 | ### iOS 9-12
59 | 1. Откройте браузер Safari, на мобильном устройстве и введите там `http://IP:735/webapp`, где IP это зарезервированный постоянный IP вашего компьютера.
60 | 2. Нажмите кнопку `Поделиться` → `На экран Домой`. На рабочем столе появится ярлык для EasyNotes.
61 |
62 | Также если у вас iOS 6-8, можно использовать [старую версию веб-приложения](https://github.com/r57zone/EasyNotes/releases/download/0.8.7/EasyNotes.iOS.6-8.support.fix.zip).
63 |
64 | ### Синхронизация мобильных приложений по P2P (опционально, в случае проблем)
65 | Проверьте брандмауэр Windows, разрешены ли входящие подключения у вашего типа сети (частной) и разрешите если отключены.
66 |
67 | Далее для приложений Windows, Android и iOS 13+ можно включить автопоиск IP-адреса, и попробовать синхронизироваться. Если синхронизация не работает или у вас более старая iOS, то попробуйте проделать следующее:
68 | 1. Зарезервируйте постоянный IP адрес компьютеру, с Windows приложением. Это делается в настройках Wi-Fi роутера, в разделе "DHCP".
69 | 2. Зарезервируйте постоянный IP адрес мобильного устройства и добавьте его, если он отсуствует, в настройках приложения для Windows. Также можно открыть доступ для всех IP адресов (небезопасно). При необходимости удалите ненужные IP адреса.
70 |
71 | ### Настройка веб-синхронизации
72 | Следуйте инструкциям описанном [здесь](https://github.com/r57zone/EasyNotes/tree/master/Source/Web).
73 |
74 | ## Скриншоты
75 | ### Windows
76 | [](https://github.com/user-attachments/assets/36da3bcd-ac0d-474c-a733-dc70f4b035f7)
77 | [](https://github.com/user-attachments/assets/33a7e206-ae5a-438d-b1c2-92a2b95070a5)
78 |
79 | ### Android / iOS
80 | [](https://github.com/user-attachments/assets/3e241777-79cf-4cdc-ab20-b322a0d2f099)
81 | [](https://github.com/user-attachments/assets/6496fda0-4566-4eae-80d6-0fb7fa1ae880)
82 | [](https://github.com/user-attachments/assets/4cec5cb1-4bf8-4f9a-98e8-ce646bab1998)
83 |
84 | >На втором изображении показана установка приложения для iOS с офлайн работой и синхронизацией, с помощью стороннего приложения HTML Viewer Q.
85 |
86 |
87 | >На третьем изображении показана установка PWA или HTML приложения. PWA может синхронизироваться только с https серверами. HTML приложения могут работать офлайн только до iOS 13, начиная с iOS 13 для офлайн работы нужно будет использовать предыдущий метод.
88 |
89 | ## Загрузка
90 | >Версии для Android 7.1+, iOS 9+ и Windows 7+ (с установленным Internet Explorer 11).
91 |
92 | **[Загрузить](https://github.com/r57zone/EasyNotes/releases)**
93 |
94 | ## Обратная связь
95 | `r57zone[собака]gmail.com`
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/r57zone/EasyNotes/)
2 | [](https://github.com/r57zone/EasyNotes/blob/master/README.RU.md)
3 | ← Choose language | Выберите язык
4 |
5 | # EasyNotes
6 | 
7 |
8 | Note apps for Windows, Android and iOS, with direct local sync or web server sync. The server can be either a Windows application (you need to run it for synchronization) or your web server. The API documentation can be found [here](https://github.com/r57zone/EasyNotes/blob/master/API.md).
9 |
10 | ## Features
11 | The following languages are supported: English, Russian, Chinese (Traditional), Spanish, Portuguese (Brazilian Portuguese), French, German, Japanese, Arabic, Italian and Korean.
12 |
13 | 
14 | 
15 | 
16 | 
17 | 
18 | 
19 | 
20 | 
21 | 
22 | 
23 | 
24 | 
25 | 
26 | 
27 |
28 |
29 | Apps support a dark theme with automatic switching during night time.
30 |
31 |
32 | There is full support for tablets.
33 |
34 |
35 | If you want to leave the old date when editing a note then on mobile phones you need to click on the date and on the PC hold down the `Shift` key when you click on the done button.
36 |
37 |
38 | There is a 5-megabyte limit for notes (except PC), you can monitor the available storage in the application settings.
39 |
40 | ## Setup
41 | ### Windows
42 | For Windows there are 2 applications, one is a server application that other client applications synchronize with, and the other is a client application that synchronizes with a server application or web server.
43 |
44 | ### Android
45 | Install `EasyNotes.apk`, select automatic IP address search or enter a reserved permanent IP of your computer (more on this below). If your router assigns the following IP addresses: `192.168.0.0/15`, `192.168.0.100/115`, `192.168.1.0/15`, `192.168.1.100/115`, `192.168.2.0/15`, `192.168.3.0/15`, then you can simply enable automatic IP address search, and the application will automatically detect your computer.
46 |
47 | ### iOS 13+
48 | If you want to synchronize directly with a PC or http web server, you need to do the following:
49 | 1. Download the archive "EasyNotes.iOS.zip", unzip it to the EasyNotes folder and place the folder in [Apple iCloud](https://www.icloud.com/iclouddrive/), also create an `images` folder and move the images from `EasyNotes\images` there.
50 | 2. Install the [HTML Viewer Q](https://apps.apple.com/us/app/html-viewer-q/id810042973) application (or any other application that can display HTML and allows Internet connections).
51 | 3. Launch the `HTML Viewer Q` application, click the files icon (5th from the bottom). Click on `Browse`, go to iCloud Drive, then to `Applications` and click on the `EasyNotes` folder to move, then move the folder to `iPhone/HTML Viewer`.
52 | 4. Next, open `index.html`, then close and reopen the `HTML Viewer Q` application, after which the application will work and all styles will be displayed.
53 | 5. In the application settings, you can disable `Tabbed Browsing` to disable the top bar with switching HTML pages.
54 |
55 |
56 | If you just want to use the application without synchronization or want to synchronize with an https web server, then you need to do the following:
57 | 1. Open the Safari browser on your mobile device and enter `https://easynotespwa.github.io` there.
58 | 2. Click the `Share` button → `Add to Home Screen`. A shortcut to EasyNotes will appear on the desktop.
59 |
60 | ### iOS 9-12
61 | 1. Open Safari browser on your mobile device and enter `http://IP:735/webapp`, where IP is the reserved permanent IP of your computer.
62 | 2. Click the `Share` button → `Add to Home Screen`. A shortcut to EasyNotes will appear on your desktop.
63 |
64 | Also, if you have iOS 6-8, you can download and use [the legacy version of the web app](https://github.com/r57zone/EasyNotes/releases/download/0.8.7/EasyNotes.iOS.6-8.support.fix.zip).
65 |
66 | ### P2P mobile app synchronization (optional, in case of problems)
67 | Check Windows firewall to see if incoming connections are allowed for your network type (private) and allow if disabled.
68 |
69 | Next, for Windows, Android and iOS 13+ apps, you can enable automatic IP address search and try to sync. If synchronization does not work or you have an older iOS, try the following:
70 | 1. Reserve a permanent IP address for the computer with the Windows app. This is done in the Wi-Fi router settings, in the "DHCP" section.
71 | 2. Reserve a permanent IP address for the mobile device and add it, if it is missing, in the Windows app settings. You can also open access for all IP addresses (unsafe). If necessary, delete unnecessary IP addresses.
72 |
73 | ### Setup web sync
74 | Follow the instructions described [here](https://github.com/r57zone/EasyNotes/tree/master/Source/Web).
75 |
76 | ## Screenshots
77 | ### Windows
78 | [](https://github.com/user-attachments/assets/928a044c-921e-4780-aa4b-81c1ab86d89b)
79 | [](https://github.com/user-attachments/assets/21b2a33c-13cd-44fd-a501-1be23a3d7d57)
80 |
81 | ### Android / iOS
82 | [](https://github.com/user-attachments/assets/bbb6e01a-abe3-4b72-bcba-0817f3d88c06)
83 | [](https://github.com/user-attachments/assets/a6988b94-1d23-4497-b5f6-6b46dc8e8115)
84 | [](https://github.com/user-attachments/assets/f56a9649-6220-405e-a0e0-a021280c613b)
85 |
86 | >The second image shows the installation of an iOS app with offline work and synchronization, using a third-party application HTML Viewer Q.
87 |
88 |
89 | >The third image shows the installation of a PWA or HTML app. PWA can only synchronize with https servers. HTML apps can work offline only up to iOS 13, starting from iOS 13, for offline work you will need to use the previous method.
90 |
91 | ## Download
92 | >Versions for Android 7.1+, iOS 9+ and Windows 7+ (with Internet Explorer 11 installed).
93 |
94 | **[Download](https://github.com/r57zone/EasyNotes/releases)**
95 |
96 | ## Feedback
97 | `r57zone[at]gmail.com`
--------------------------------------------------------------------------------
/Source/Android/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/Source/Android/.idea/assetWizardSettings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
326 |
327 |
--------------------------------------------------------------------------------
/Source/Android/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Source/Android/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
18 |
19 |
--------------------------------------------------------------------------------
/Source/Android/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Source/Android/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/Source/Android/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'org.jetbrains.kotlin.android'
4 | }
5 |
6 | android {
7 | namespace 'com.r57zone.easynotes'
8 | compileSdk 32
9 |
10 | defaultConfig {
11 | applicationId "com.r57zone.easynotes"
12 | minSdk 25
13 | targetSdk 32
14 | versionCode 22
15 | versionName "1.2.0"
16 |
17 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
18 | }
19 |
20 | buildTypes {
21 | release {
22 | minifyEnabled false
23 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
24 | }
25 | }
26 | compileOptions {
27 | sourceCompatibility JavaVersion.VERSION_1_8
28 | targetCompatibility JavaVersion.VERSION_1_8
29 | }
30 | kotlinOptions {
31 | jvmTarget = '1.8'
32 | }
33 |
34 | dependenciesInfo {
35 | // Disables dependency metadata when building APKs.
36 | includeInApk = false
37 | // Disables dependency metadata when building Android App Bundles.
38 | includeInBundle = false
39 | }
40 | }
41 |
42 | dependencies {
43 |
44 | implementation 'com.android.support:appcompat-v7:28.0.0'
45 | implementation 'com.android.support.constraint:constraint-layout:2.0.4'
46 | testImplementation 'junit:junit:4.13.2'
47 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
48 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
49 | }
--------------------------------------------------------------------------------
/Source/Android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/Source/Android/app/src/androidTest/java/com/r57zone/easynotes/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.r57zone.easynotes
2 |
3 | import android.support.test.InstrumentationRegistry
4 | import android.support.test.runner.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22 | assertEquals("com.r57zone.easynotes", appContext.packageName)
23 | }
24 | }
--------------------------------------------------------------------------------
/Source/Android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
17 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/Source/Android/app/src/main/assets/ReadMe.txt:
--------------------------------------------------------------------------------
1 | En: Place files from "Source/Multi" folder.
2 |
3 | Ru: Положите файлы из папки "Source/Multi".
--------------------------------------------------------------------------------
/Source/Android/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Android/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/Source/Android/app/src/main/java/com/r57zone/easynotes/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.r57zone.easynotes
2 |
3 | import android.annotation.SuppressLint
4 | import android.annotation.TargetApi
5 | import android.os.Build
6 | import android.os.Bundle
7 | import android.support.v7.app.AppCompatActivity
8 | import android.webkit.WebChromeClient
9 | import android.webkit.WebResourceRequest
10 | import android.webkit.WebView
11 | import android.webkit.WebViewClient
12 | import android.content.Intent
13 | import android.net.Uri
14 |
15 | class MainActivity : AppCompatActivity() {
16 | @SuppressLint("SetJavaScriptEnabled")
17 | override fun onCreate(savedInstanceState: Bundle?) {
18 | super.onCreate(savedInstanceState)
19 | setContentView(R.layout.activity_main)
20 | supportActionBar?.hide() /* Спрятать sidebar */
21 |
22 | val webView = findViewById(R.id.webView)
23 | webView.getSettings().setJavaScriptEnabled(true)
24 | webView.getSettings().domStorageEnabled = true // Включение localStorage
25 | webView.loadUrl("file:///android_asset/index.html")
26 |
27 | val webViewClient: WebViewClient = object : WebViewClient() {
28 | @Deprecated("Deprecated in Java")
29 | override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
30 | if (url.startsWith("http://") || url.startsWith("https://")) { // Добавлена проверка внешних ссылок
31 | view.context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
32 | return true
33 | }
34 | view.loadUrl(url)
35 | return false
36 | }
37 |
38 | @TargetApi(Build.VERSION_CODES.N)
39 | override fun shouldOverrideUrlLoading(
40 | view: WebView,
41 | request: WebResourceRequest
42 | ): Boolean {
43 | //view.loadUrl(request.url.toString())
44 | //return true
45 | // Открытие во внешнем браузере
46 | val url = request.url.toString()
47 | if (url.startsWith("http://") || url.startsWith("https://")) {
48 | view.context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
49 | return true
50 | } else {
51 | return false
52 | }
53 | }
54 | }
55 |
56 | webView.setWebViewClient(webViewClient)
57 | webView.webChromeClient = WebChromeClient() // Включаение confirm & alert
58 | }
59 | }
--------------------------------------------------------------------------------
/Source/Android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/Source/Android/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/Source/Android/app/src/main/res/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Android/app/src/main/res/icon.png
--------------------------------------------------------------------------------
/Source/Android/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Source/Android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Source/Android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Source/Android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/Source/Android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/Source/Android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/Source/Android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/Source/Android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/Source/Android/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
--------------------------------------------------------------------------------
/Source/Android/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #017d93
4 | #017d93
5 | #202329
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
--------------------------------------------------------------------------------
/Source/Android/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #F6F6F7
4 |
--------------------------------------------------------------------------------
/Source/Android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | EasyNotes
3 |
--------------------------------------------------------------------------------
/Source/Android/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
--------------------------------------------------------------------------------
/Source/Android/app/src/main/res/xml/backup_rules.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
13 |
--------------------------------------------------------------------------------
/Source/Android/app/src/main/res/xml/data_extraction_rules.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 |
13 |
19 |
--------------------------------------------------------------------------------
/Source/Android/app/src/test/java/com/r57zone/easynotes/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.r57zone.easynotes
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
--------------------------------------------------------------------------------
/Source/Android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | plugins {
3 | id 'com.android.application' version '7.3.0' apply false
4 | id 'com.android.library' version '7.3.0' apply false
5 | id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
6 | }
--------------------------------------------------------------------------------
/Source/Android/clear.bat:
--------------------------------------------------------------------------------
1 | rd /s /q .gradle
2 | rd /s /q build
3 | rd /s /q app\build
4 | del local.properties
--------------------------------------------------------------------------------
/Source/Android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # Kotlin code style for this project: "official" or "obsolete":
15 | kotlin.code.style=official
16 | # Enables namespacing of each library's R class so that its R class includes only the
17 | # resources declared in the library itself and none from the library's dependencies,
18 | # thereby reducing the size of the R class for that library
19 | android.nonTransitiveRClass=true
--------------------------------------------------------------------------------
/Source/Android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/Source/Android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Dec 07 13:11:58 GMT+04:00 2023
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/Source/Android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/Source/Android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/Source/Android/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | google()
5 | mavenCentral()
6 | }
7 | }
8 | dependencyResolutionManagement {
9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
10 | repositories {
11 | google()
12 | mavenCentral()
13 | }
14 | }
15 | rootProject.name = "EasyNotes"
16 | include ':app'
17 |
--------------------------------------------------------------------------------
/Source/Multi/any.css:
--------------------------------------------------------------------------------
1 | /* Android / Windows tablet mode */
2 | @media all and (min-width:550px) {
3 | #list{display:block; float:left; width:37%;}
4 | #list #items{border-right:1px solid var(--list-right-border-color);}
5 | .sub-panel{background-color:var(--background-color);}
6 | #editor{display:block; float:right; width:63%;}
7 | #settings{float:right; width:63%;}
8 | .hide-btn img{opacity:0; cursor:default;}
9 | }
--------------------------------------------------------------------------------
/Source/Multi/app.manifest:
--------------------------------------------------------------------------------
1 | CACHE MANIFEST
2 |
3 | CACHE:
4 | /langs.js
5 | /style.css
6 | /android.css
7 | /ios.css
8 | /images/back.png
9 | /images/close.png
10 | /images/done.png
11 | /images/new.png
12 | /images/rm.png
13 | /images/settings.png
14 | /images/sync.png
15 | /manifest.json
16 | /icons/icon.png
17 | /icons/icon-180.png
18 |
19 | NETWORK:
20 | *
--------------------------------------------------------------------------------
/Source/Multi/icons/icon-114.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Multi/icons/icon-114.png
--------------------------------------------------------------------------------
/Source/Multi/icons/icon-120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Multi/icons/icon-120.png
--------------------------------------------------------------------------------
/Source/Multi/icons/icon-144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Multi/icons/icon-144.png
--------------------------------------------------------------------------------
/Source/Multi/icons/icon-152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Multi/icons/icon-152.png
--------------------------------------------------------------------------------
/Source/Multi/icons/icon-180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Multi/icons/icon-180.png
--------------------------------------------------------------------------------
/Source/Multi/icons/icon-72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Multi/icons/icon-72.png
--------------------------------------------------------------------------------
/Source/Multi/icons/icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Multi/icons/icon-76.png
--------------------------------------------------------------------------------
/Source/Multi/icons/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Multi/icons/icon.png
--------------------------------------------------------------------------------
/Source/Multi/images/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Multi/images/back.png
--------------------------------------------------------------------------------
/Source/Multi/images/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Multi/images/close.png
--------------------------------------------------------------------------------
/Source/Multi/images/done.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Multi/images/done.png
--------------------------------------------------------------------------------
/Source/Multi/images/flashlight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Multi/images/flashlight.png
--------------------------------------------------------------------------------
/Source/Multi/images/folders.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Multi/images/folders.png
--------------------------------------------------------------------------------
/Source/Multi/images/new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Multi/images/new.png
--------------------------------------------------------------------------------
/Source/Multi/images/qr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Multi/images/qr.png
--------------------------------------------------------------------------------
/Source/Multi/images/rm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Multi/images/rm.png
--------------------------------------------------------------------------------
/Source/Multi/images/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Multi/images/search.png
--------------------------------------------------------------------------------
/Source/Multi/images/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Multi/images/settings.png
--------------------------------------------------------------------------------
/Source/Multi/images/share.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Multi/images/share.png
--------------------------------------------------------------------------------
/Source/Multi/images/sync.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Multi/images/sync.png
--------------------------------------------------------------------------------
/Source/Multi/ios.css:
--------------------------------------------------------------------------------
1 | /* iOS fixes */
2 | html{-webkit-text-size-adjust: 100%; /* Prevent font scaling in landscape while allowing user zoom */}
3 | body, textarea {font-family: '-apple-system', Helvetica, HelveticaNeue;}
4 | #settings #controls #item .title {margin-top: -1px;}
5 |
6 | /*
7 | /* General settings for all models / Общие настройки для всех моделей
8 | iPhone SE 2016 - 320x568
9 | */
10 |
11 | /* Most iPhones / Большинство айфонов */
12 | @media only screen and (min-width: 321px) and (orientation: portrait) {
13 | #btn {padding: 0 10px;}
14 | #list #items #note #title {margin-left: 18px;}
15 | #list #items #note #date {margin-right: 20px;}
16 | #notification {padding: 13px 0 30px 0;}
17 |
18 | #list #items{height: calc(100% - 105px);}
19 | #editor #page{height: calc(100% - 105px);}
20 | .sub-panel{height:60px; align-items: flex-start;}
21 | }
22 |
23 | @media only screen and (min-width: 569px) and (orientation: landscape) {
24 | #btn {padding: 0 20px;}
25 | #list #items #note #title {margin-left: 46px;}
26 | #list #items #note #date {margin-right: 48px;}
27 |
28 | #editor #memo {width: calc(100% - 76px);}
29 | }
30 |
31 | /* iPhone X, XS, 11 Pro, 12 Mini */
32 | @media only screen and (device-width: 375px) and (device-height: 812px) {}
33 |
34 | /* iPhone 12, 12 Pro */
35 | @media only screen and (device-width: 390px) and (device-height: 844px) {}
36 |
37 | /* iPhone XR, 11, iPhone XS Max, 11 Pro Max */
38 | @media only screen and (device-width: 414px) and (device-height: 896px) {}
39 |
40 | /* iPhone 12 Pro Max */
41 | @media only screen and (device-width: 428px) and (device-height: 926px) {}
42 |
43 | /* iPhone 13, 13 Pro, 14, 14 Pro, 15, 15 Pro */
44 | @media only screen and (device-width: 390px) and (device-height: 844px) { /* iPhone 13 & 14 */ }
45 | @media only screen and (device-width: 430px) and (device-height: 932px) { /* iPhone 14 Pro Max */ }
46 | @media only screen and (device-width: 430px) and (device-height: 932px) { /* iPhone 15 & 15 Pro */ }
47 |
--------------------------------------------------------------------------------
/Source/Multi/langs.js:
--------------------------------------------------------------------------------
1 | // Перевод, по умолчанию English
2 | let IDS_MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
3 | let IDS_DAYOFWEEK = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
4 | let IDS_TODAY = 'Today';
5 | let IDS_YESTERDAY = 'Yesterday';
6 | let IDS_DAYSAGO = 'days ago';
7 | let IDS_NEW_NOTE = 'New note';
8 | let IDS_NOTES = 'Notes';
9 | let IDS_SEARCH = 'Search...';
10 |
11 | // Настройки
12 | let IDS_SETTINGS = 'Settings';
13 | let IDS_SYNC_ADDRESS = 'IP or domain';
14 | let IDS_SYNC_PORT = 'Port';
15 | let IDS_AUTOSEARCH_IP = 'Autosearch IP address';
16 | let IDS_ABOUT_SYNC = 'IP and port or domain to sync notes with your PC or web server.';
17 | let IDS_AUTO_SYNC = 'Sync at startup';
18 | let IDS_ABOUT_AUTO_SYNC = 'Automatically sync on app launch.';
19 |
20 | // Для всех
21 | let IDS_FULL_RESET = 'Full reset';
22 | let IDS_CONFIRM_FULL_RESET = 'Do you really want to reset everything? All notes and settings will be deleted.';
23 | let IDS_DARK_THEME = 'Dark theme';
24 | let IDS_THEME_TIME_DEPENDENT = 'Theme is time dependent';
25 | let IDS_DARK_THEME_START = 'Dark theme start';
26 | let IDS_DARK_THEME_END = 'Dark theme end';
27 | let IDS_ABOUT_THEME_TIME = 'The dark theme is enabled automatically by time. Specify the time in 24-hour format.';
28 | let IDS_CATEGORIES = 'Categories';
29 | let IDS_CATEGORIES_LIST = '#Shopping\n#Ideas\n#Work\n#Projects\n#Family\n#Health\n#Finances\n#Education\n#Travel\n#Hobbies\n#Personal';
30 | let IDS_LAST_UPDATE = 'Last update: ';
31 | let IDS_LOCAL_STORAGE = 'Local storage: %s of 5000 KB';
32 |
33 | // Уведомления
34 | let IDS_DATE_UPDATE = 'Date will be update';
35 | let IDS_DATE_NOT_UPDATE = 'Date will not be update';
36 | let IDS_AUTH_REJECT = 'Authorization rejected';
37 | let IDS_SYNC_SUCCESSFUL = 'Sync successful';
38 | let IDS_SYNC_ERROR = 'Sync error';
39 | let IDS_SYNC_NEED_CONNECT = 'Need connect to the network for sync';
40 | let IDS_CONNECTION_FAILED = 'Connection failed';
41 |
42 | // Русский язык
43 | if (navigator.language.toLowerCase() == 'ru-ru' || navigator.language == 'ru') { // В iOS языки прописными буквами, вторая проверка нужна для Edge
44 | IDS_MONTHS = ['янв.', 'фев.', 'мар.', 'апр.', 'май', 'июн.', 'июл.', 'авг.', 'сен.', 'окт.', 'ноя.', 'дек.'];
45 | IDS_DAYOFWEEK = ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье'];
46 | IDS_TODAY = 'Сегодня';
47 | IDS_YESTERDAY = 'Вчера';
48 | IDS_DAYSAGO = 'дн. назад';
49 | IDS_NEW_NOTE = 'Новая заметка';
50 | IDS_NOTES = 'Заметки';
51 | IDS_SEARCH = 'Поиск...';
52 |
53 | // Настройки
54 | IDS_SETTINGS = 'Настройки';
55 | IDS_SYNC_ADDRESS = 'IP или домен';
56 | IDS_SYNC_PORT = 'Порт';
57 | IDS_AUTOSEARCH_IP = 'Автопоиск IP адреса';
58 | IDS_ABOUT_SYNC = 'IP адрес и порт или домен для синхронизации заметок, с вашим ПК или веб-сервером.';
59 | IDS_AUTO_SYNC = 'Синхронизация при запуске';
60 | IDS_ABOUT_AUTO_SYNC = 'Автоматическая синхронизация при запуске приложения.';
61 |
62 | // Для всех
63 | IDS_FULL_RESET = 'Полный сброс';
64 | IDS_CONFIRM_FULL_RESET = 'Вы действительно хотите сбросить всё? Все заметки и настройки будут удалены.';
65 | IDS_DARK_THEME = 'Темная тема';
66 | IDS_THEME_TIME_DEPENDENT = 'Тема в зависимости от времени';
67 | IDS_DARK_THEME_START = 'Начало тёмной темы';
68 | IDS_DARK_THEME_END = 'Конец тёмной темы';
69 | IDS_ABOUT_THEME_TIME = 'Тёмная тема включается автоматически по времени. Укажите часы в 24-часовом формате.';
70 | IDS_CATEGORIES = 'Категории';
71 | IDS_CATEGORIES_LIST = '#Покупки\n#Идеи\n#Работа\n#Проекты\n#Семья\n#Здоровье\n#Финансы\n#Учеба\n#Путешествия\n#Хобби\n#Личное';
72 | IDS_LAST_UPDATE = 'Последнее обновление: ';
73 | IDS_LOCAL_STORAGE = 'Локальное хранилище: %s из 5000 Кб';
74 |
75 | // Уведомления
76 | IDS_DATE_UPDATE = 'Дата обновится';
77 | IDS_DATE_NOT_UPDATE = 'Дата не обновится';
78 | IDS_AUTH_REJECT = 'Авторизация отклонена';
79 | IDS_SYNC_SUCCESSFUL = 'Синхронизация успешно завершена';
80 | IDS_SYNC_ERROR = 'Ошибка синхронизации';
81 | IDS_SYNC_NEED_CONNECT = 'Для синхронизации нужно подключиться к сети';
82 | IDS_CONNECTION_FAILED = 'Cоединение не удалось';
83 |
84 | // Chinese
85 | } else if (navigator.language.toLowerCase() == 'zh-cn' || navigator.language == 'zh-tw' || navigator.language == 'zh') {
86 | IDS_MONTHS = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'];
87 | IDS_DAYOFWEEK = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期天'];
88 | IDS_TODAY = '今天';
89 | IDS_YESTERDAY = '昨天';
90 | IDS_DAYSAGO = '天前';
91 | IDS_NEW_NOTE = '新笔记';
92 | IDS_NOTES = '笔记';
93 | IDS_SEARCH = '搜索...';
94 |
95 | // 设置
96 | IDS_SETTINGS = '设置';
97 | IDS_SYNC_ADDRESS = 'IP 或 域名';
98 | IDS_SYNC_PORT = '端口';
99 | IDS_AUTOSEARCH_IP = '自动搜索 IP 地址';
100 | IDS_ABOUT_SYNC = '用于同步笔记的 IP 地址和端口或域名,与你的 PC 或网站服务器同步。';
101 | IDS_AUTO_SYNC = '启动时同步';
102 | IDS_ABOUT_AUTO_SYNC = '在启动应用时自动同步。';
103 |
104 | // 对所有人
105 | IDS_FULL_RESET = '完全重置';
106 | IDS_CONFIRM_FULL_RESET = '你确定要重置所有内容吗?所有笔记和设置将被删除。';
107 | IDS_DARK_THEME = '黑暗主题';
108 | IDS_THEME_TIME_DEPENDENT = '根据时间设置主题';
109 | IDS_DARK_THEME_START = '黑暗主题开始';
110 | IDS_DARK_THEME_END = '黑暗主题结束';
111 | IDS_ABOUT_THEME_TIME = '黑暗主题会根据时间自动启用。请以 24 小时格式指定时间。';
112 | IDS_CATEGORIES = '类别';
113 | IDS_CATEGORIES_LIST = '#购物\n#创意\n#工作\n#项目\n#家庭\n#健康\n#财务\n#学习\n#旅行\n#爱好\n#个人';
114 | IDS_LAST_UPDATE = '最后更新时间:';
115 | IDS_LOCAL_STORAGE = '本地存储:%s / 5000 KB';
116 |
117 | // 通知
118 | IDS_DATE_UPDATE = '日期将更新';
119 | IDS_DATE_NOT_UPDATE = '日期不会更新';
120 | IDS_AUTH_REJECT = '授权被拒绝';
121 | IDS_SYNC_SUCCESSFUL = '同步成功';
122 | IDS_SYNC_ERROR = '同步错误';
123 | IDS_SYNC_NEED_CONNECT = '需要连接到网络才能同步';
124 | IDS_CONNECTION_FAILED = '连接失败';
125 |
126 | // Spanish
127 | } else if (navigator.language.toLowerCase() == 'es-es' || navigator.language == 'es') {
128 | IDS_MONTHS = ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Set', 'Oct', 'Nov', 'Dic'];
129 | IDS_DAYOFWEEK = ['Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado', 'Domingo'];
130 | IDS_TODAY = 'Hoy';
131 | IDS_YESTERDAY = 'Ayer';
132 | IDS_DAYSAGO = 'días atrás';
133 | IDS_NEW_NOTE = 'Nueva nota';
134 | IDS_NOTES = 'Notas';
135 |
136 | IDS_SETTINGS = 'Configuración';
137 | IDS_SYNC_ADDRESS = 'IP o dominio';
138 | IDS_SYNC_PORT = 'Puerto';
139 | IDS_AUTOSEARCH_IP = 'Buscar dirección IP automáticamente';
140 | IDS_ABOUT_SYNC = 'IP y puerto o dominio para sincronizar notas con tu PC o servidor web.';
141 | IDS_AUTO_SYNC = 'Sincronizar al inicio';
142 | IDS_ABOUT_AUTO_SYNC = 'Sincronizar automáticamente al iniciar la aplicación.';
143 |
144 | IDS_FULL_RESET = 'Restablecer';
145 | IDS_CONFIRM_FULL_RESET = 'Realmente deseas restablecer todo? Todas las notas y ajustes serán eliminados.';
146 | IDS_DARK_THEME = 'Tema oscuro';
147 | IDS_THEME_TIME_DEPENDENT = 'Tema es dependiente del tiempo';
148 | IDS_DARK_THEME_START = 'Inicio del tema oscuro';
149 | IDS_DARK_THEME_END = 'Fin del tema oscuro';
150 | IDS_ABOUT_THEME_TIME = 'El tema oscuro se activa automáticamente según la hora. Indique la hora en formato de 24 horas.';
151 | IDS_CATEGORIES = 'Categorías';
152 | IDS_CATEGORIES_LIST = '#Compras\n#Ideas\n#Trabajo\n#Proyectos\n#Familia\n#Salud\n#Finanzas\n#Estudios\n#Viajes\n#Aficiones\n#Personal';
153 | IDS_LAST_UPDATE = 'Última actualización: ';
154 | IDS_LOCAL_STORAGE = 'Almacenamiento local: %s de 5000 KB';
155 |
156 | IDS_DATE_UPDATE = 'La fecha se actualizará';
157 | IDS_DATE_NOT_UPDATE = 'La fecha no se actualizará';
158 | IDS_AUTH_REJECT = 'Autorización rechazada';
159 | IDS_SYNC_SUCCESSFUL = 'Sincronización exitosa';
160 | IDS_SYNC_ERROR = 'Error de sincronización';
161 | IDS_SYNC_NEED_CONNECT = 'Necesita conectarse a la red para sincronizar';
162 | IDS_CONNECTION_FAILED = 'Error de conexión';
163 |
164 | // Portuguese (Brazilian Portuguese)
165 | } else if (navigator.language.toLowerCase() == 'pt-br' || navigator.language == 'pt') {
166 | IDS_MONTHS = ['jan.', 'fev.', 'mar.', 'abr.', 'mai', 'jun.', 'jul.', 'ago.', 'set.', 'out.', 'nov.', 'dez.'];
167 | IDS_DAYOFWEEK = ['Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sábado', 'Domingo'];
168 | IDS_TODAY = 'Hoje';
169 | IDS_YESTERDAY = 'Ontem';
170 | IDS_DAYSAGO = 'dias atrás';
171 | IDS_NEW_NOTE = 'Nova nota';
172 | IDS_NOTES = 'Notas';
173 | IDS_SEARCH = 'Buscar...';
174 |
175 | // Configurações
176 | IDS_SETTINGS = 'Configurações';
177 | IDS_SYNC_ADDRESS = 'IP ou domínio';
178 | IDS_SYNC_PORT = 'Porta';
179 | IDS_AUTOSEARCH_IP = 'Busca automática de IP';
180 | IDS_ABOUT_SYNC = 'Endereço IP e porta ou domínio para sincronizar as notas com seu PC ou servidor web.';
181 | IDS_AUTO_SYNC = 'Sincronização ao iniciar';
182 | IDS_ABOUT_AUTO_SYNC = 'Sincronização automática ao iniciar o aplicativo.';
183 |
184 | // Para todos
185 | IDS_FULL_RESET = 'Redefinição total';
186 | IDS_CONFIRM_FULL_RESET = 'Você realmente deseja redefinir tudo? Todas as notas e configurações serão excluídas.';
187 | IDS_DARK_THEME = 'Tema escuro';
188 | IDS_THEME_TIME_DEPENDENT = 'Tema dependendo da hora';
189 | IDS_DARK_THEME_START = 'Início do tema escuro';
190 | IDS_DARK_THEME_END = 'Fim do tema escuro';
191 | IDS_ABOUT_THEME_TIME = 'O tema escuro é ativado automaticamente com base no horário. Informe a hora no formato de 24 horas.';
192 | IDS_CATEGORIES = 'Categorias';
193 | IDS_CATEGORIES_LIST = '#Compras\n#Ideias\n#Trabalho\n#Projetos\n#Família\n#Saúde\n#Finanças\n#Estudos\n#Viagens\n#Hobbies\n#Pessoal';
194 | IDS_LAST_UPDATE = 'Última atualização: ';
195 | IDS_LOCAL_STORAGE = 'Armazenamento local: %s de 5000 KB';
196 |
197 | // Notificações
198 | IDS_DATE_UPDATE = 'Data será atualizada';
199 | IDS_DATE_NOT_UPDATE = 'Data não será atualizada';
200 | IDS_AUTH_REJECT = 'Autenticação rejeitada';
201 | IDS_SYNC_SUCCESSFUL = 'Sincronização concluída com sucesso';
202 | IDS_SYNC_ERROR = 'Erro de sincronização';
203 | IDS_SYNC_NEED_CONNECT = 'Para sincronizar, é necessário conectar à rede';
204 | IDS_CONNECTION_FAILED = 'Falha na conexão';
205 |
206 | // French
207 | } else if (navigator.language.toLowerCase() == 'fr' || navigator.language == 'fr-fr') {
208 | IDS_MONTHS = ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.', 'août', 'sept.', 'oct.', 'nov.', 'déc.'];
209 | IDS_DAYOFWEEK = ['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche'];
210 | IDS_TODAY = 'Aujourd\'hui';
211 | IDS_YESTERDAY = 'Hier';
212 | IDS_DAYSAGO = 'jours avant';
213 | IDS_NEW_NOTE = 'Nouvelle note';
214 | IDS_NOTES = 'Notes';
215 | IDS_SEARCH = 'Recherche...';
216 |
217 | // Paramètres
218 | IDS_SETTINGS = 'Paramètres';
219 | IDS_SYNC_ADDRESS = 'IP ou domaine';
220 | IDS_SYNC_PORT = 'Port';
221 | IDS_AUTOSEARCH_IP = 'Recherche automatique de l\'IP';
222 | IDS_ABOUT_SYNC = 'Adresse IP et port ou domaine pour synchroniser les notes avec votre PC ou serveur web.';
223 | IDS_AUTO_SYNC = 'Synchronisation au démarrage';
224 | IDS_ABOUT_AUTO_SYNC = 'Synchronisation automatique au démarrage de l\'application.';
225 |
226 | // Pour tous
227 | IDS_FULL_RESET = 'Réinitialisation complète';
228 | IDS_CONFIRM_FULL_RESET = 'Voulez-vous vraiment réinitialiser tout ? Toutes les notes et paramètres seront supprimés.';
229 | IDS_DARK_THEME = 'Thème sombre';
230 | IDS_THEME_TIME_DEPENDENT = 'Thème selon l\'heure';
231 | IDS_DARK_THEME_START = 'Début du thème sombre';
232 | IDS_DARK_THEME_END = 'Fin du thème sombre';
233 | IDS_ABOUT_THEME_TIME = 'Le thème sombre est activé automatiquement en fonction de l\'heure. Indiquez l\'heure au format 24 heures.';
234 | IDS_CATEGORIES = 'Catégories';
235 | IDS_CATEGORIES_LIST = '#Achats\n#Idées\n#Travail\n#Projets\n#Famille\n#Santé\n#Finances\n#Études\n#Voyages\n#Loisirs\n#Personnel';
236 | IDS_LAST_UPDATE = 'Dernière mise à jour : ';
237 | IDS_LOCAL_STORAGE = 'Stockage local : %s sur 5000 Ko';
238 |
239 | // Notifications
240 | IDS_DATE_UPDATE = 'La date sera mise à jour';
241 | IDS_DATE_NOT_UPDATE = 'La date ne sera pas mise à jour';
242 | IDS_AUTH_REJECT = 'Authentification rejetée';
243 | IDS_SYNC_SUCCESSFUL = 'Synchronisation réussie';
244 | IDS_SYNC_ERROR = 'Erreur de synchronisation';
245 | IDS_SYNC_NEED_CONNECT = 'Pour synchroniser, vous devez vous connecter au réseau';
246 | IDS_CONNECTION_FAILED = 'Échec de la connexion';
247 |
248 | // German
249 | } else if (navigator.language.toLowerCase() == 'de-de' || navigator.language == 'de') {
250 | IDS_MONTHS = ['Jan.', 'Feb.', 'März', 'Apr.', 'Mai', 'Juni', 'Juli', 'Aug.', 'Sept.', 'Okt.', 'Nov.', 'Dez.'];
251 | IDS_DAYOFWEEK = ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag'];
252 | IDS_TODAY = 'Heute';
253 | IDS_YESTERDAY = 'Gestern';
254 | IDS_DAYSAGO = 'Tg. her';
255 | IDS_NEW_NOTE = 'Neue Notiz';
256 | IDS_NOTES = 'Notizen';
257 | IDS_SEARCH = 'Suche...';
258 |
259 | IDS_SETTINGS = 'Einstellungen';
260 | IDS_SYNC_ADDRESS = 'IP oder Domain';
261 | IDS_SYNC_PORT = 'Port';
262 | IDS_AUTOSEARCH_IP = 'IP-Adresse automatisch suchen';
263 | IDS_ABOUT_SYNC = 'IP-Adresse und Port oder Domain zur Synchronisierung von Notizen mit Ihrem PC oder Webserver.';
264 | IDS_AUTO_SYNC = 'Synchronisierung beim Start';
265 | IDS_ABOUT_AUTO_SYNC = 'Automatische Synchronisierung beim Start der Anwendung.';
266 |
267 | IDS_FULL_RESET = 'Komplett zurücksetzen';
268 | IDS_CONFIRM_FULL_RESET = 'Sind Sie sicher, dass Sie alles zurücksetzen möchten? Alle Notizen und Einstellungen werden gelöscht.';
269 | IDS_DARK_THEME = 'Dunkles Thema';
270 | IDS_THEME_TIME_DEPENDENT = 'Thema abhängig von der Zeit';
271 | IDS_DARK_THEME_START = 'Beginn des Dunkelmodus';
272 | IDS_DARK_THEME_END = 'Ende des Dunkelmodus';
273 | IDS_ABOUT_THEME_TIME = 'Das dunkle Design wird automatisch mit der Zeit aktiviert. Geben Sie die Uhrzeit im 24-Stunden-Format an.';
274 | IDS_CATEGORIES = 'Kategorien';
275 | IDS_CATEGORIES_LIST = '#Einkäufe\n#Ideen\n#Arbeit\n#Projekte\n#Familie\n#Gesundheit\n#Finanzen\n#Studium\n#Reisen\n#Hobbys\n#Persönlich';
276 | IDS_LAST_UPDATE = 'Letzte Aktualisierung: ';
277 | IDS_LOCAL_STORAGE = 'Lokaler Speicher: %s von 5000 KB';
278 |
279 | IDS_DATE_UPDATE = 'Datum wird aktualisiert';
280 | IDS_DATE_NOT_UPDATE = 'Datum wird nicht aktualisiert';
281 | IDS_AUTH_REJECT = 'Authentifizierung abgelehnt';
282 | IDS_SYNC_SUCCESSFUL = 'Synchronisierung erfolgreich abgeschlossen';
283 | IDS_SYNC_ERROR = 'Synchronisierungsfehler';
284 | IDS_SYNC_NEED_CONNECT = 'Zur Synchronisierung müssen Sie sich verbinden';
285 | IDS_CONNECTION_FAILED = 'Verbindung fehlgeschlagen';
286 |
287 | // Japanese
288 | } else if (navigator.language.toLowerCase() == 'ja' || navigator.language == 'ja-jp') {
289 | IDS_MONTHS = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'];
290 | IDS_DAYOFWEEK = ['月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日', '日曜日'];
291 | IDS_TODAY = '今日';
292 | IDS_YESTERDAY = '昨日';
293 | IDS_DAYSAGO = '日前';
294 | IDS_NEW_NOTE = '新しいメモ';
295 | IDS_NOTES = 'メモ';
296 | IDS_SEARCH = '検索...';
297 |
298 | // 設定
299 | IDS_SETTINGS = '設定';
300 | IDS_SYNC_ADDRESS = 'IP または ドメイン';
301 | IDS_SYNC_PORT = 'ポート';
302 | IDS_AUTOSEARCH_IP = 'IPアドレスの自動検索';
303 | IDS_ABOUT_SYNC = 'ノートをPCまたはウェブサーバーと同期するためのIPアドレスとポートまたはドメイン。';
304 | IDS_AUTO_SYNC = '起動時同期';
305 | IDS_ABOUT_AUTO_SYNC = 'アプリケーション起動時に自動的に同期します。';
306 |
307 | // 全ての設定
308 | IDS_FULL_RESET = '完全リセット';
309 | IDS_CONFIRM_FULL_RESET = '本当にすべてリセットしますか?すべてのメモと設定が削除されます。';
310 | IDS_DARK_THEME = 'ダークテーマ';
311 | IDS_THEME_TIME_DEPENDENT = '時間帯によるテーマ';
312 | IDS_DARK_THEME_START = 'ダークテーマの開始';
313 | IDS_DARK_THEME_END = 'ダークテーマの終了';
314 | IDS_ABOUT_THEME_TIME = 'ダークテーマは自動的に時間に基づいて有効になります。24時間形式で時間を指定してください。';
315 | IDS_CATEGORIES = 'カテゴリー';
316 | IDS_CATEGORIES_LIST = '#買い物\n#アイデア\n#仕事\n#プロジェクト\n#家族\n#健康\n#財務\n#勉強\n#旅行\n#趣味\n#個人的';
317 | IDS_LAST_UPDATE = '最終更新: ';
318 | IDS_LOCAL_STORAGE = 'ローカルストレージ: %s / 5000 KB';
319 |
320 | // 通知
321 | IDS_DATE_UPDATE = '日付が更新されます';
322 | IDS_DATE_NOT_UPDATE = '日付は更新されません';
323 | IDS_AUTH_REJECT = '認証が拒否されました';
324 | IDS_SYNC_SUCCESSFUL = '同期が成功しました';
325 | IDS_SYNC_ERROR = '同期エラー';
326 | IDS_SYNC_NEED_CONNECT = '同期するには ネットワークに接続する必要があります';
327 | IDS_CONNECTION_FAILED = '接続に失敗しました';
328 |
329 | // Arabic
330 | } else if (navigator.language.toLowerCase() == 'ar' || navigator.language == 'ar-sa') {
331 | IDS_MONTHS = ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'];
332 | IDS_DAYOFWEEK = ['الإثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت', 'الأحد'];
333 | IDS_TODAY = 'اليوم';
334 | IDS_YESTERDAY = 'أمس';
335 | IDS_DAYSAGO = 'منذ أيام';
336 | IDS_NEW_NOTE = 'ملاحظة جديدة';
337 | IDS_NOTES = 'الملاحظات';
338 | IDS_SEARCH = 'بحث...';
339 |
340 | // الإعدادات
341 | IDS_SETTINGS = 'الإعدادات';
342 | IDS_SYNC_ADDRESS = 'IP أو نطاق';
343 | IDS_SYNC_PORT = 'المنفذ';
344 | IDS_AUTOSEARCH_IP = 'البحث التلقائي عن عنوان IP';
345 | IDS_ABOUT_SYNC = 'عنوان IP والمنفذ أو النطاق لمزامنة الملاحظات مع جهاز الكمبيوتر أو الخادم الويب الخاص بك.';
346 | IDS_AUTO_SYNC = 'المزامنة عند بدء التشغيل';
347 | IDS_ABOUT_AUTO_SYNC = 'المزامنة التلقائية عند تشغيل التطبيق.';
348 |
349 | // للجميع
350 | IDS_FULL_RESET = 'إعادة ضبط كاملة';
351 | IDS_CONFIRM_FULL_RESET = 'هل ترغب حقًا في إعادة ضبط كل شيء؟ سيتم حذف جميع الملاحظات والإعدادات.';
352 | IDS_DARK_THEME = 'السمة الداكنة';
353 | IDS_THEME_TIME_DEPENDENT = 'السمة حسب الوقت';
354 | IDS_DARK_THEME_START = 'بداية السمة الداكنة';
355 | IDS_DARK_THEME_END = 'نهاية السمة الداكنة';
356 | IDS_ABOUT_THEME_TIME = 'يتم تفعيل السمة الداكنة تلقائيًا وفقًا للوقت. حدد الساعة بتنسيق 24 ساعة.';
357 | IDS_CATEGORIES = 'الفئات';
358 | IDS_CATEGORIES_LIST = '#التسوق\n#أفكار\n#عمل\n#مشاريع\n#عائلة\n#صحة\n#المالية\n#دراسة\n#سفر\n#هوايات\n#شخصي';
359 | IDS_LAST_UPDATE = 'آخر تحديث: ';
360 | IDS_LOCAL_STORAGE = 'التخزين المحلي: %s من 5000 كيلوبايت';
361 |
362 | // الإشعارات
363 | IDS_DATE_UPDATE = 'سيتم تحديث التاريخ';
364 | IDS_DATE_NOT_UPDATE = 'لن يتم تحديث التاريخ';
365 | IDS_AUTH_REJECT = 'تم رفض المصادقة';
366 | IDS_SYNC_SUCCESSFUL = 'تمت المزامنة بنجاح';
367 | IDS_SYNC_ERROR = 'خطأ في المزامنة';
368 | IDS_SYNC_NEED_CONNECT = 'لإجراء المزامنة، يجب الاتصال بالشبكة';
369 | IDS_CONNECTION_FAILED = 'فشل الاتصال';
370 |
371 | // Italian
372 | } else if (navigator.language.toLowerCase() == 'it' || navigator.language == 'it-it') {
373 | IDS_MONTHS = ['gen.', 'feb.', 'mar.', 'apr.', 'mag.', 'giu.', 'lug.', 'ago.', 'set.', 'ott.', 'nov.', 'dic.'];
374 | IDS_DAYOFWEEK = ['Lunedì', 'Martedì', 'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato', 'Domenica'];
375 | IDS_TODAY = 'Oggi';
376 | IDS_YESTERDAY = 'Ieri';
377 | IDS_DAYSAGO = 'giorni fa';
378 | IDS_NEW_NOTE = 'Nuova nota';
379 | IDS_NOTES = 'Note';
380 | IDS_SEARCH = 'Cerca...';
381 |
382 | // Impostazioni
383 | IDS_SETTINGS = 'Impostazioni';
384 | IDS_SYNC_ADDRESS = 'IP o dominio';
385 | IDS_SYNC_PORT = 'Porta';
386 | IDS_AUTOSEARCH_IP = 'Ricerca automatica IP';
387 | IDS_ABOUT_SYNC = 'Indirizzo IP e porta o dominio per sincronizzare le note con il tuo PC o server web.';
388 | IDS_AUTO_SYNC = 'Sincronizzazione all\'avvio';
389 | IDS_ABOUT_AUTO_SYNC = 'Sincronizzazione automatica all\'avvio dell\'applicazione.';
390 |
391 | // Per tutti
392 | IDS_FULL_RESET = 'Ripristino completo';
393 | IDS_CONFIRM_FULL_RESET = 'Vuoi davvero ripristinare tutto? Tutte le note e le impostazioni verranno eliminate.';
394 | IDS_DARK_THEME = 'Tema scuro';
395 | IDS_THEME_TIME_DEPENDENT = 'Tema in base all\'ora';
396 | IDS_DARK_THEME_START = 'Inizio tema scuro';
397 | IDS_DARK_THEME_END = 'Fine tema scuro';
398 | IDS_ABOUT_THEME_TIME = 'Il tema scuro si attiva automaticamente in base all\'ora. Inserisci l\'ora nel formato 24 ore.';
399 | IDS_CATEGORIES = 'Categorie';
400 | IDS_CATEGORIES_LIST = '#Shopping\n#Idee\n#Lavoro\n#Progetti\n#Famiglia\n#Salute\n#Finanze\n#Studio\n#Viaggi\n#Hobby\n#Personale';
401 | IDS_LAST_UPDATE = 'Ultimo aggiornamento: ';
402 | IDS_LOCAL_STORAGE = 'Archiviazione locale: %s su 5000 KB';
403 |
404 | // Notifiche
405 | IDS_DATE_UPDATE = 'La data verrà aggiornata';
406 | IDS_DATE_NOT_UPDATE = 'La data non verrà aggiornata';
407 | IDS_AUTH_REJECT = 'Autenticazione rifiutata';
408 | IDS_SYNC_SUCCESSFUL = 'Sincronizzazione riuscita';
409 | IDS_SYNC_ERROR = 'Errore di sincronizzazione';
410 | IDS_SYNC_NEED_CONNECT = 'Per sincronizzare, è necessario connettersi alla rete';
411 | IDS_CONNECTION_FAILED = 'Connessione fallita';
412 |
413 | // Korean
414 | } else if (navigator.language.toLowerCase() == 'ko' || navigator.language == 'ko-kr') {
415 | IDS_MONTHS = ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'];
416 | IDS_DAYOFWEEK = ['월요일', '화요일', '수요일', '목요일', '금요일', '토요일', '일요일'];
417 | IDS_TODAY = '오늘';
418 | IDS_YESTERDAY = '어제';
419 | IDS_DAYSAGO = '일 전';
420 | IDS_NEW_NOTE = '새 메모';
421 | IDS_NOTES = '메모';
422 | IDS_SEARCH = '검색...';
423 |
424 | // 설정
425 | IDS_SETTINGS = '설정';
426 | IDS_SYNC_ADDRESS = 'IP 또는 도메인';
427 | IDS_SYNC_PORT = '포트';
428 | IDS_AUTOSEARCH_IP = 'IP 자동 검색';
429 | IDS_ABOUT_SYNC = '노트를 PC 또는 웹 서버와 동기화하기 위한 IP 주소와 포트 또는 도메인.';
430 | IDS_AUTO_SYNC = '시작 시 동기화';
431 | IDS_ABOUT_AUTO_SYNC = '앱 시작 시 자동 동기화.';
432 |
433 | // 모두
434 | IDS_FULL_RESET = '전체 초기화';
435 | IDS_CONFIRM_FULL_RESET = '정말 모든 것을 초기화하시겠습니까? 모든 메모와 설정이 삭제됩니다.';
436 | IDS_DARK_THEME = '어두운 테마';
437 | IDS_THEME_TIME_DEPENDENT = '시간에 따른 테마';
438 | IDS_DARK_THEME_START = '어두운 테마 시작';
439 | IDS_DARK_THEME_END = '어두운 테마 종료';
440 | IDS_ABOUT_THEME_TIME = '어두운 테마는 자동으로 시간에 맞춰 활성화됩니다. 24시간 형식으로 시간을 지정하세요.';
441 | IDS_CATEGORIES = '카테고리';
442 | IDS_CATEGORIES_LIST = '#쇼핑\n#아이디어\n#일\n#프로젝트\n#가족\n#건강\n#재정\n#학습\n#여행\n#취미\n#개인';
443 | IDS_LAST_UPDATE = '마지막 업데이트: ';
444 | IDS_LOCAL_STORAGE = '로컬 저장소: %s / 5000 KB';
445 |
446 | // 알림
447 | IDS_DATE_UPDATE = '날짜가 업데이트됩니다';
448 | IDS_DATE_NOT_UPDATE = '날짜가 업데이트되지 않습니다';
449 | IDS_AUTH_REJECT = '인증 거부';
450 | IDS_SYNC_SUCCESSFUL = '동기화 성공';
451 | IDS_SYNC_ERROR = '동기화 오류';
452 | IDS_SYNC_NEED_CONNECT = '동기화를 위해서는 네트워크에 연결해야 합니다';
453 | IDS_CONNECTION_FAILED = '연결 실패';
454 | }
--------------------------------------------------------------------------------
/Source/Multi/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Updating EasyNotes",
3 | "short_name": "EasyNotes",
4 | "description": "App for notes.",
5 | "start_url": ".",
6 | "display": "standalone",
7 | "background_color": "#f8f8f8",
8 | "theme_color": "#f8f8f8",
9 | "icons": [
10 | {
11 | "src": "icon/icon.png",
12 | "sizes": "128x128",
13 | "type": "image/png",
14 | "purpose": "any"
15 | },
16 | {
17 | "src": "icon/icon-180.png",
18 | "sizes": "180x180",
19 | "type": "image/png",
20 | "purpose": "maskable"
21 | }
22 | ]
23 | }
--------------------------------------------------------------------------------
/Source/Multi/pwa.js:
--------------------------------------------------------------------------------
1 | // https://github.com/Oshanotter/offline-pwa-example/
2 |
3 | const PRECACHE = 'precache-v1';
4 |
5 | // A list of local resources we always want to be cached.
6 | const PRECACHE_URLS = [
7 | 'index.html',
8 | './', // Alias for index.html
9 | 'langs.js',
10 | 'style.css',
11 | 'android.css',
12 | 'ios.css',
13 | 'images/back.png',
14 | 'images/close.png',
15 | 'images/done.png',
16 | 'images/new.png',
17 | 'images/rm.png',
18 | 'images/settings.png',
19 | 'images/sync.png',
20 | 'pwa.js',
21 | 'manifest.json',
22 | 'icons/icon.png',
23 | 'icons/icon-180.png'
24 | ];
25 |
26 | // The install handler takes care of precaching the resources we always need.
27 | self.addEventListener('install', event => {
28 | event.waitUntil(
29 | caches.open(PRECACHE)
30 | .then(cache => cache.addAll(PRECACHE_URLS))
31 | .then(self.skipWaiting())
32 | );
33 | });
34 |
35 | // The activate handler takes care of cleaning up old caches.
36 | self.addEventListener('activate', event => {
37 | const currentCaches = [PRECACHE];
38 | event.waitUntil(
39 | caches.keys().then(cacheNames => {
40 | return cacheNames.filter(cacheName => !currentCaches.includes(cacheName));
41 | }).then(cachesToDelete => {
42 | return Promise.all(cachesToDelete.map(cacheToDelete => {
43 | return caches.delete(cacheToDelete);
44 | }));
45 | }).then(() => self.clients.claim())
46 | );
47 | });
48 |
49 | // On fetch, use cache but update the entry with the latest contents from the server.
50 | self.addEventListener('fetch', function(evt) {
51 | // If the request doesn't come from the same origin as the referrer, don't store it
52 | if (!evt.request.url.includes(evt.request.referrer)){
53 | return; // You can also remove the return statement if you want every request to be cached
54 | }
55 | // You can use respondWith() to answer ASAP…
56 | evt.respondWith(fromCache(evt.request));
57 | // ...and waitUntil() to prevent the worker to be killed until the cache is updated.
58 | evt.waitUntil(
59 | update(evt.request)
60 | );
61 | });
62 |
63 | // Open the cache where the assets were stored and search for the requested resource. Notice that in case of no matching, the promise still resolves but it does with undefined as value.
64 | function fromCache(request) {
65 | return caches.open(PRECACHE).then(function(cache) {
66 | return cache.match(request);
67 | });
68 | }
69 |
70 | // Update consists in opening the cache, performing a network request and storing the new response data.
71 | function update(request) {
72 | return caches.open(PRECACHE).then(function(cache) {
73 | return fetch(request).then(function(response) {
74 | return cache.put(request, response.clone()).then(function() {
75 | return response;
76 | });
77 | });
78 | });
79 | }
--------------------------------------------------------------------------------
/Source/Multi/style.css:
--------------------------------------------------------------------------------
1 | :root{
2 | --background-color: #f8f8f8;
3 | --panel-background-color: #017d93;
4 | --text-color: #333;
5 |
6 | --meta-color: #ac5942;
7 | --sub-panel-background-color: #e7e7e7;
8 |
9 | --list-color:black;
10 |
11 | --items-background-color: #fff;
12 |
13 | --items-border-color: #ededed;
14 | --item-hover-background-color: #ededed;
15 | --category-hover-background-color: #ededed;
16 | --date-color: #454545;
17 |
18 | --settings-item-border-color: #dbdbdb;
19 |
20 | --title-box-color: #333;
21 |
22 | --notification-border-color: #bdbdbd;
23 |
24 | --list-right-border-color: #d5d5d5;
25 | }
26 |
27 | /* Dark Theme */
28 | html[data-theme="dark"] {
29 | --background-color: #2a3035;
30 | --panel-background-color: #202329;
31 | --text-color: white;
32 |
33 | --meta-color: #787c81;
34 | --sub-panel-background-color: #202329;
35 | --list-color:#ededef;
36 |
37 | --items-background-color: #202329;
38 | --items-border-color: #3a404a;
39 | --item-hover-background-color: #202329;
40 | --category-hover-background-color: #2a3035;
41 | --date-color: #787c81;
42 | --settings-item-border-color:#3a404a;
43 |
44 | --title-box-color: #787c81;
45 | --notification-border-color: black;
46 |
47 | --list-right-border-color: #202329;
48 | }
49 |
50 | html,body{padding:0;margin:0;}
51 | body{font-family: Arial, sans-serif; font-size:16px; color:var(--text-color); background-color:var(--background-color); -webkit-user-select:none; -webkit-tap-highlight-color:transparent;}
52 | a{text-decoration:none; color:gray;}
53 | #container{position:absolute; width:100%; height:100%;}
54 |
55 | /* Action bar */
56 | #panel{position:absolute; display:flex; flex-direction:row; justify-content:space-between; align-items:center; width:inherit; height:45px; overflow:hidden; background-color:var(--panel-background-color); color:white; text-align:center; cursor:default;}
57 | #panel-bg{width:inherit; height:45px;}
58 | #btn{width:45px; height:45px; cursor:pointer; display:flex; justify-content:center; align-items:center; flex-shrink:0; transition:transform 1s ease;}
59 | #btn:hover{opacity:0.7;}
60 | #btn img{max-width:100%;}
61 | .rotateBtn{transform:rotate(360deg);}
62 | #panel .title{font-weight:500px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
63 | #panel-qr{display:none; position:absolute; width:100%; height:45px; background: rgba(0,0,0,0.5); flex-direction:row; justify-content:space-between; align-items:center;}
64 |
65 | /* List of notes */
66 | #list{width:100%; height:100%; color:var(--list-color);}
67 | #list #items{height:calc(100% - 90px); overflow-y:auto; -webkit-overflow-scrolling:touch;}
68 | #list #items #note{display:flex; flex-direction:row; justify-content:space-between; align-items:center; cursor:pointer; height:44px; border-bottom:1px solid var(--items-border-color); overflow:hidden;}
69 | #list #items #note:hover{background-color:var(--item-hover-background-color);}
70 | #list #items #note #title{margin-left:8px; margin-right:4px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
71 | #list #items #note #date{margin-right:10px; margin-left:4px; color:var(--date-color); font-size:13px; white-space:nowrap; text-align:right;}
72 | #list #search-block{display:none; width:calc(100% - 135px);}
73 | #list input[type=text]{padding:5px 10px; max-width:calc(100% - 26px); border:1px solid var(--settings-item-border-color); border-radius:8px; font-size:16px; outline:none; background-color: var(--items-background-color); color:var(--text-color);}
74 | #list input[type=text]:hover,#list input[type=text]:active,#list input[type=text]:focus{border:1px solid #3498db;}
75 |
76 | /* Note editor */
77 | #editor{display:none; width:100%; height:100%;}
78 | #editor #page{height:calc(100% - 90px);}
79 | #meta{display:flex; flex-direction:row; justify-content:space-between; align-items:center; color:var(--meta-color); height:32px; width:100%; cursor:default; overflow:hidden; white-space:nowrap;}
80 | #meta #DaysAgo{margin-left:12px;}
81 | #meta #DateNote{margin-right:12px;}
82 | #note-categories {
83 | display: none;
84 | position: absolute;
85 | height: 200px;
86 | overflow-y: scroll;
87 | bottom: 50px;
88 | right: 10px;
89 | border-radius: 5px;
90 | background-color: var(--items-background-color);
91 | transition: opacity 0.3s;
92 | box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
93 | border: 1px solid var(--settings-item-border-color);
94 | color: var(--list-color);
95 | }
96 | #note-categories #item{display:flex;
97 | justify-content:space-between;
98 | align-items:center;
99 | cursor:pointer;
100 | height:32px;
101 | padding:4px 8px;
102 | text-align:center;
103 | border-bottom:1px solid var(--items-border-color);
104 | }
105 | #note-categories #item:hover{background-color:var(--category-hover-background-color);}
106 | #note-categories #item:last-child {border-bottom:none;}
107 |
108 |
109 | #editor #memo{display:block; width:calc(100% - 24px); height:calc(100% - 45px); padding:4px 0; margin:0 auto; background-color:transparent; border:none;}
110 | textarea{font-weight:normal; font-size:17px; font-family: Arial, sans-serif; color:var(--text-color); overflow-y:auto; -webkit-overflow-scrolling:touch; resize:none; border-radius:0; -webkit-tap-highlight-color:rgba(0,0,0,0);}
111 | textarea:focus{outline:none;}
112 | .sub-panel{display:flex; flex-direction:row; justify-content:space-between; align-items:center; height:45px; overflow:hidden; text-align:center; cursor:default;}
113 |
114 | /* Settings */
115 | #settings{display:none; width:100%; height:100%;}
116 | #settings #page{height:calc(100% - 45px); overflow-y:auto; -webkit-overflow-scrolling:touch;}
117 | #settings #page #items:first-child{margin-top:3px;}
118 | #settings #items{padding:10px 0; margin:0 auto; width:92%; overflow:hidden; font-size:14px;}
119 | #settings #items #item{display:flex; flex-direction:row; justify-content:space-between; align-items:center; text-overflow:ellipsis; overflow:hidden; white-space:nowrap; border:1px solid var(--settings-item-border-color); padding:14px 8px; background-color:var(--items-background-color); border-top:none; color:var(--text-color);}
120 | #settings #items #item:first-child{border-top-left-radius:15px; border-top-right-radius:15px; border:1px solid var(--settings-item-border-color);}
121 | #settings #items #item:last-child{border-bottom-left-radius:15px; border-bottom-right-radius:15px;}
122 | #settings #items #item .title{margin-left:4px;}
123 | #settings #items #item #control{text-align:right; margin-right:4px;}
124 | #settings .titlebox{padding:5px 0; margin:0 auto; width:87%; font-size:14px; color:var(--title-box-color);}
125 | #settings input[type=text],#settings input[type=number]{border:none; padding:0 7px; background-color:transparent; outline:none; font-size:14px; -webkit-tap-highlight-color:rgba(0,0,0,0); text-align:right; color:var(--text-color);}
126 | #settings input[type=text]:focus,#settings input[type=number]:focus{background-color:transparent;}
127 | #settings input::-webkit-outer-spin-button,#settings input::-webkit-inner-spin-button{-webkit-appearance: none; margin:0;}
128 | #settings input[type=number]{-moz-appearance: textfield;} /* Firefox */
129 | .switch{position:relative; display:inline-block; width:40px; height:20px; background-color:#7e7e7e; border-radius:20px; top:3px;}
130 | .switch::after{content:''; position:absolute; width:18px; height:18px; border-radius:50%; background-color:white; top:1px; left:1px;}
131 | .checkbox:checked + .switch::after{left:20px;}
132 | .checkbox:checked + .switch{background-color:#3498db;}
133 | .checkbox{display:none;}
134 | #settings textarea{padding:5px; max-width:100%; border:1px solid var(--settings-item-border-color); border-radius:8px; font-size:14px; outline:none; background-color: var(--items-background-color); }
135 | #settings textarea:hover,#settings textarea:active,#settings textarea:focus{border:1px solid #3498db;}
136 |
137 | /* Notification */
138 | #notification{position:absolute; bottom:0; width:100%; padding: 15px 0; visibility:hidden; font-size:14px; background-color:var(--sub-panel-background-color); text-align:center; border-top:1px solid var(--notification-border-color);}
139 | #notification.show{visibility:visible; animation:fadein 0.5s, fadeout 0.5s 3s;}
140 | @keyframes fadein{from {opacity: 0;} to {opacity: 1;}}
141 | @keyframes fadeout{from {opacity: 1;} to {opacity: 0;}}
142 |
143 | #sync-progress{display:none; position:absolute; bottom:0; width:100%; height:4px; background-color:blue; background:linear-gradient(to left, transparent, transparent, #23A6D5, transparent, transparent); background-size:200% 200%; animation:move-background 2s linear infinite;}
144 | @keyframes move-background{0% {background-position:100% 0%} 100% {background-position:-100% 0%}}
145 |
146 | /* Layout switching animation */
147 | #list,#editor,#settings{animation:fadeInFromNone 0.5s ease-out;}
148 | @keyframes fadeInFromNone{
149 | 0%{display:none; opacity:0;}
150 | 1% {display:block; opacity:0;}
151 | 100%{display:block; opacity:1;}
152 | }
--------------------------------------------------------------------------------
/Source/Multi/windows.css:
--------------------------------------------------------------------------------
1 | /* Windows client */
2 | body{font-size:14px;}
3 | #panel,#panel-bg{height:40px;}
4 | #panel .title{font-size:16px;}
5 | #btn{width:40px; height:40px;}
6 | #list #items{font-size:14px; height:calc(100% - 80px)}
7 | #list #items #note{height:40px;}
8 | #editor #page{height:calc(100% - 80px);}
9 | #editor #memo{height:calc(100% - 40px); font-size:14px;}
10 | .sub-panel{height:40px;}
11 | #settings #page{height:calc(100% - 40px);}
12 | #settings #items{font-size:14px;}
13 | #settings #items #item{padding:10px 5px;}
14 | #settings #items #item:first-child{border-top-left-radius:10px; border-top-right-radius:10px;}
15 | #settings #items #item:last-child{border-bottom-left-radius:10px; border-bottom-right-radius:10px;}
16 | input::-webkit-outer-spin-button, input::-webkit-inner-spin-button {-webkit-appearance: none; margin: 0;}
--------------------------------------------------------------------------------
/Source/Web/ReadMe.txt:
--------------------------------------------------------------------------------
1 | Notes synchronization web server for EasyNotes.
2 |
3 | En:
4 | 1. Unzip the contents of the "Web" folder to your web hosting.
5 |
6 | 2. Change the mysql database settings in the "api/config.php" settings file.
7 |
8 | 3. In the Windows (client) and Android application settings, enter your domain address, for example, "http://example.com" and port 80.
9 |
10 | 4. For iOS 13+, copy the files from the "Source/Multi" directory to the web hosting folder. If the hosting has a security certificate (https), you can enable PWA so that the application works offline. To enable PWA, change the "let IsPWA = false;" parameter to let IsPWA = true; in the "index.html" file, you can also change the "let UseManualAddress = true;" parameter to "let UseManualAddress = false;" to disable server change settings in the application.
11 |
12 | For iOS 9-12, copy the files from the "Source/Windows/webapp" directory (Windows applications) to the root of your web hosting, then go to your domain, adding the file to "/getnotes.php" to the link, so that it looks like "http://example.com/getnotes.php", after which you can install the web application on iOS. More details in the main instructions.
13 |
14 | 5. Sync all your devices and close access to sync new devices by changing the parameter in the settings file "api/config.php".
15 |
16 |
17 | Ru:
18 | 1. Распакуйте содержимое папки "Web" на ваш веб-хостинг.
19 |
20 | 2. Измените параметры базы данных mysql в файле настроек "api/config.php".
21 |
22 | 3. В настройках приложений для Windows (клиент) и Android введите адрес вашего домена, например, "http://example.com" и 80 порт.
23 |
24 | 4. Для iOS 13+ скопируйте файлы из каталога "Source/Multi", в папку веб-хостинга. Если хостинг имеет сертификат безопасности (https), то можно включить PWA, чтобы приложение работало офлайн. Для включения PWA измените параметр "let IsPWA = false;" на let IsPWA = true; в файле "index.html", также можно изменить параметр "let UseManualAddress = true;" на "let UseManualAddress = false;", чтобы отключить параметры изменения сервера, в приложении.
25 |
26 | Для iOS 9-12 скопируйте в корень вашего веб-хостинга файлы из каталога "Source/Windows/webapp" (приложения для Windows), после чего перейдите на ваш домен, добавив в ссылку файл на "/getnotes.php", чтобы вышло примерно следующее "http://example.com/getnotes.php", после чего можно установить веб-приложение на iOS. Подробнее в основной инструкции.
27 |
28 | 5. Синхронизируйте все ваши устройства и закройте доступ для синхронизации новых устройств, изменив параметр в файле настроек "api/config.php".
--------------------------------------------------------------------------------
/Source/Web/api/.htaccess:
--------------------------------------------------------------------------------
1 | AddDefaultCharset UTF-8
2 |
3 | RewriteEngine on
4 | RewriteRule ^([^.?]+)$ %{REQUEST_URI}.php [L]
5 | RewriteCond %{THE_REQUEST} "^[^ ]* .*?\.php[? ].*$"
6 | RewriteRule .* - [L,R=404]
7 |
8 |
9 | FileETag None
10 |
11 | Header unset ETag
12 | Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
13 | Header set Pragma "no-cache"
14 | Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
15 |
16 |
--------------------------------------------------------------------------------
/Source/Web/api/actions.php:
--------------------------------------------------------------------------------
1 | \n";
23 | if ($result && mysqli_num_rows($result) > 0) {
24 | for ($i=0; $i < mysqli_num_rows($result); $i++) {
25 | $action = $result->fetch_assoc();
26 | echo "\t" . '<' . $action['Action'] . ' id="' . $action['ID'] . '" datetime="' . $action['DateTime'] . '">' . $action['Note'] . '' . $action['Action'] . '>' . "\n";
27 | }
28 | }
29 | echo '';
30 |
31 | if ($conn)
32 | mysqli_close($conn);
33 |
34 | ?>
--------------------------------------------------------------------------------
/Source/Web/api/auth.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Source/Web/api/config.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Source/Web/api/notes.php:
--------------------------------------------------------------------------------
1 | \n";
25 | if ($result && mysqli_num_rows($result) > 0) {
26 | for ($i=0; $i < mysqli_num_rows($result); $i++) {
27 | $note = $result->fetch_assoc();
28 | echo "\t" . '' . $note['Note'] . '' . "\n";
29 | }
30 | }
31 | echo '';
32 |
33 | if ($conn)
34 | mysqli_close($conn);
35 |
36 | ?>
--------------------------------------------------------------------------------
/Source/Web/api/received.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Source/Web/api/syncnotes.php:
--------------------------------------------------------------------------------
1 | x52';
28 | if ($postdata != '') {
29 | $xml = simplexml_load_string($postdata);
30 | foreach($xml->children() as $child) {
31 | if ($child->getName() == 'insert')
32 | $result = mysqli_query($conn, "INSERT INTO notes (ID, Note, DateTime) VALUES (" . $child['id'] .", \"$child\", " . $child['datetime'] . ")");
33 | else if ($child->getName() == 'update')
34 | $result = mysqli_query($conn, "UPDATE notes SET Note=\"$child\", DateTime=" . $child['datetime'] . " WHERE ID=" . $child['id']);
35 | else if ($child->getName() == 'delete')
36 | $result = mysqli_query($conn, "DELETE FROM notes WHERE ID=" . $child['id']);
37 | foreach ($AuthorizedDevices as $DeviceDBName)
38 | if ($child->getName() != 'delete')
39 | $result = mysqli_query($conn, "INSERT INTO $DeviceDBName (Action, ID, Note, DateTime) VALUES (\"" . $child->getName() . "\", " . $child['id'] .", \"$child\", " . $child['datetime'] . ")");
40 | else
41 | $result = mysqli_query($conn, "INSERT INTO $DeviceDBName (Action, ID, Note, DateTime) VALUES (\"" . $child->getName() . "\", " . $child['id'] .", \"\", 0)");
42 | }
43 |
44 | if ($result)
45 | echo 'ok';
46 | else
47 | echo 'auth:denied';
48 | }
49 |
50 | // $fp = @fopen("sniff.txt", "a");
51 | // @fputs($fp, "$postdata\n");
52 | // @fputs($fp, "INSERT INTO $DeviceDBName (Action, ID, Note, DateTime) VALUES (\"" . $child->getName() . "\", " . $child['id'] .", \"\", " . $child['datetime'] . ")\n");
53 | // @fclose($fp);
54 |
55 | if ($conn)
56 | mysqli_close($conn);
57 | ?>
--------------------------------------------------------------------------------
/Source/Web/cachemanifest.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Source/Web/getnotes.php:
--------------------------------------------------------------------------------
1 | ', '', $source);
4 | ?>
--------------------------------------------------------------------------------
/Source/Windows/AllowedIPs.txt:
--------------------------------------------------------------------------------
1 | 127.0.0.1
2 | 192.168.0.1
3 | 192.168.0.2
4 | 192.168.0.3
5 | 192.168.0.4
6 | 192.168.0.5
7 | 192.168.0.6
8 | 192.168.0.7
9 | 192.168.0.8
10 | 192.168.0.9
11 | 192.168.0.10
12 | 192.168.0.100
13 | 192.168.0.101
14 | 192.168.0.102
15 | 192.168.0.103
16 | 192.168.0.104
17 | 192.168.0.105
18 | 192.168.0.106
19 | 192.168.0.107
20 | 192.168.0.108
21 | 192.168.0.109
22 | 192.168.0.110
23 | 192.168.1.0
24 | 192.168.1.1
25 | 192.168.1.2
26 | 192.168.1.3
27 | 192.168.1.4
28 | 192.168.1.5
29 | 192.168.1.6
30 | 192.168.1.7
31 | 192.168.1.8
32 | 192.168.1.9
33 | 192.168.1.10
34 | 192.168.1.100
35 | 192.168.1.101
36 | 192.168.1.102
37 | 192.168.1.103
38 | 192.168.1.104
39 | 192.168.1.105
40 | 192.168.1.106
41 | 192.168.1.107
42 | 192.168.1.108
43 | 192.168.1.109
44 | 192.168.1.110
45 | 192.168.2.0
46 | 192.168.2.1
47 | 192.168.2.2
48 | 192.168.2.3
49 | 192.168.2.4
50 | 192.168.2.5
51 | 192.168.2.6
52 | 192.168.2.7
53 | 192.168.2.8
54 | 192.168.2.9
55 | 192.168.2.10
56 | 192.168.3.0
57 | 192.168.3.1
58 | 192.168.3.2
59 | 192.168.3.3
60 | 192.168.3.4
61 | 192.168.3.5
62 | 192.168.3.6
63 | 192.168.3.7
64 | 192.168.3.8
65 | 192.168.3.9
66 | 192.168.3.10
67 |
--------------------------------------------------------------------------------
/Source/Windows/LangFile.pas:
--------------------------------------------------------------------------------
1 | unit LangFile;
2 |
3 | interface
4 |
5 | uses
6 | Classes, SysUtils, Generics.Collections;
7 |
8 | type
9 | TLangFile = class
10 | private
11 | FCache: TDictionary;
12 | public
13 | constructor Create(const FileName: string);
14 | destructor Destroy; override;
15 | function GetString(const Key, DefaultValue: string): string;
16 | end;
17 |
18 | implementation
19 |
20 | constructor TLangFile.Create(const FileName: string);
21 | var
22 | LangFile: TStringList;
23 | i, PosEqual: Integer;
24 | Key, Value: string;
25 | begin
26 | FCache := TDictionary.Create;
27 | LangFile := TStringList.Create;
28 | if not FileExists(FileName) then Exit;
29 | try
30 | LangFile.LoadFromFile(FileName, TEncoding.UTF8);
31 | for i := 0 to LangFile.Count - 1 do
32 | begin
33 | PosEqual := Pos('=', LangFile[i]);
34 | if PosEqual <> 0 then
35 | begin
36 | Key := Trim(Copy(LangFile[i], 1, PosEqual - 1));
37 | Value := Trim(Copy(LangFile[i], PosEqual + 1, MaxInt));
38 | FCache.Add(Key, Value);
39 | end;
40 | end;
41 | finally
42 | LangFile.Free;
43 | end;
44 | end;
45 |
46 | destructor TLangFile.Destroy;
47 | begin
48 | FCache.Free;
49 | inherited;
50 | end;
51 |
52 | function TLangFile.GetString(const Key, DefaultValue: string): string;
53 | begin
54 | if not FCache.TryGetValue(Key, Result) then
55 | Result := DefaultValue;
56 | end;
57 |
58 | end.
59 |
60 |
--------------------------------------------------------------------------------
/Source/Windows/Languages/Arabic.txt:
--------------------------------------------------------------------------------
1 | # Main
2 | NEW_NOTE=ملاحظة جديدة
3 | NOTES=الملاحظات
4 | TODAY=اليوم
5 | YESTERDAY=أمس
6 | DAYSAGO=منذ أيام
7 | SEARCH=بحث...
8 | SYNC=مزامنة
9 | DEV_SYNC_CONFIRM=الجهاز "%s" يطلب إذن للمزامنة. هل تسمح بذلك؟
10 | CUT=قص
11 | COPY=نسخ
12 | PASTE=لصق
13 | LAST_UPDATE=آخر تحديث:
14 |
15 | # Settings
16 | SETTINGS=الإعدادات
17 | INTERFACE=الواجهة
18 | DARK_THEME=الوضع المظلم
19 | THEME_TIME=الوضع يعتمد على الوقت
20 | DARK_THEME_START=بداية الوضع المظلم:
21 | DARK_THEME_END=نهاية الوضع المظلم:
22 | SYNCHRONIZATION=المزامنة
23 | SYNC_PORT=المنفذ:
24 | SYNC_WITH_ANY_IPS=المزامنة مع أي عنوان IP (غير آمن)
25 | ALLOW_IPS=العناوين المسموح بها:
26 | ALLOW_DEVS=الأجهزة المسموح بها:
27 | ALLOW_DEV_REM=إزالة الجهاز
28 | ENTER_DEV_ID=أدخل معرّف الجهاز
29 | BLOCK_REQUEST_NEW_DEVS=حظر الطلبات للأجهزة الجديدة
30 | IMPORT=استيراد
31 | EXPORT=تصدير
32 | CATEGORIES=الفئات
33 | USER_CATEGORIES=#التسوق\n#أفكار\n#عمل\n#مشاريع\n#عائلة\n#صحة\n#المالية\n#دراسة\n#سفر\n#هوايات\n#شخصي
34 | DONE=تم
35 | OK=موافق
36 | CANCEL=إلغاء
37 |
--------------------------------------------------------------------------------
/Source/Windows/Languages/Chinese.txt:
--------------------------------------------------------------------------------
1 | # Main
2 | NEW_NOTE=新笔记
3 | NOTES=笔记
4 | TODAY=今天
5 | YESTERDAY=昨天
6 | DAYSAGO=天前
7 | SEARCH=搜索...
8 | SYNC=同步
9 | DEV_SYNC_CONFIRM="设备 %s" 请求同步权限。允许吗?
10 | CUT=剪切
11 | COPY=复制
12 | PASTE=粘贴
13 | LAST_UPDATE=最后更新:
14 |
15 | # Settings
16 | SETTINGS=设置
17 | INTERFACE=界面
18 | DARK_THEME=深色主题
19 | THEME_TIME=主题根据时间变化
20 | DARK_THEME_START=深色主题开始时间:
21 | DARK_THEME_END=深色主题结束时间:
22 | SYNCHRONIZATION=同步
23 | SYNC_PORT=端口:
24 | SYNC_WITH_ANY_IPS=与任何IP同步(不安全)
25 | ALLOW_IPS=允许的IP地址:
26 | ALLOW_DEVS=允许的设备:
27 | ALLOW_DEV_REM=删除设备
28 | ENTER_DEV_ID=输入设备ID
29 | BLOCK_REQUEST_NEW_DEVS=阻止新设备的请求
30 | IMPORT=导入
31 | EXPORT=导出
32 | CATEGORIES=类别
33 | USER_CATEGORIES=#购物\n#创意\n#工作\n#项目\n#家庭\n#健康\n#财务\n#学习\n#旅行\n#爱好\n#个人
34 | DONE=完成
35 | OK=确定
36 | CANCEL=取消
--------------------------------------------------------------------------------
/Source/Windows/Languages/English.txt:
--------------------------------------------------------------------------------
1 | # Main
2 | NEW_NOTE=New note
3 | NOTES=Notes
4 | TODAY=Today
5 | YESTERDAY=Yesterday
6 | DAYSAGO=days ago
7 | SEARCH=Search...
8 | SYNC=Sync
9 | DEV_SYNC_CONFIRM=The "%s" device requests permission to sync. Allow it?
10 | CUT=Cut
11 | COPY=Copy
12 | PASTE=Paste
13 | LAST_UPDATE=Last update:
14 |
15 | # Settings
16 | SETTINGS=Settings
17 | INTERFACE=Interface
18 | DARK_THEME=Dark theme
19 | THEME_TIME=Theme is time dependent
20 | DARK_THEME_START=Dark theme start:
21 | DARK_THEME_END=Dark theme end:
22 | SYNCHRONIZATION=Synchronization
23 | SYNC_PORT=Port:
24 | SYNC_WITH_ANY_IPS=Synchronization with any IP (not secure)
25 | ALLOW_IPS=Allowed IP addresses:
26 | ALLOW_DEVS=Allowed devices:
27 | ALLOW_DEV_REM=Remove
28 | ENTER_DEV_ID=Enter the device ID
29 | BLOCK_REQUEST_NEW_DEVS=Block requests for new devices
30 | IMPORT=Import
31 | EXPORT=Export
32 | CATEGORIES=Categories
33 | USER_CATEGORIES=#Shopping\n#Ideas\n#Work\n#Projects\n#Family\n#Health\n#Finances\n#Education\n#Travel\n#Hobbies\n#Personal
34 | DONE=Done
35 | OK=OK
36 | CANCEL=Cancel
--------------------------------------------------------------------------------
/Source/Windows/Languages/French.txt:
--------------------------------------------------------------------------------
1 | # Main
2 | NEW_NOTE=Nouvelle note
3 | NOTES=Notes
4 | TODAY=Aujourd'hui
5 | YESTERDAY=Hier
6 | DAYSAGO=jours auparavant
7 | SEARCH=Rechercher...
8 | SYNC=Synchroniser
9 | DEV_SYNC_CONFIRM=L'appareil "%s" demande l'autorisation de synchroniser. Autoriser ?
10 | CUT=Couper
11 | COPY=Copier
12 | PASTE=Coller
13 | LAST_UPDATE=Dernière mise à jour :
14 |
15 | # Settings
16 | SETTINGS=Paramètres
17 | INTERFACE=Interface
18 | DARK_THEME=Thème sombre
19 | THEME_TIME=Le thème dépend du temps
20 | DARK_THEME_START=Début du thème sombre :
21 | DARK_THEME_END=Fin du thème sombre :
22 | SYNCHRONIZATION=Synchronisation
23 | SYNC_PORT=Port :
24 | SYNC_WITH_ANY_IPS=Synchronisation avec n'importe quelle adresse IP (non sécurisé)
25 | ALLOW_IPS=Adresses IP autorisées :
26 | ALLOW_DEVS=Appareils autorisés :
27 | ALLOW_DEV_REM=Supprimer
28 | ENTER_DEV_ID=Entrez l'ID de l'appareil
29 | BLOCK_REQUEST_NEW_DEVS=Bloquer les demandes de nouveaux appareils
30 | IMPORT=Importer
31 | EXPORT=Exporter
32 | CATEGORIES=Catégories
33 | USER_CATEGORIES=#Achats\n#Idées\n#Travail\n#Projets\n#Famille\n#Santé\n#Finances\n#Études\n#Voyages\n#Loisirs\n#Personnel
34 | DONE=Terminé
35 | OK=OK
36 | CANCEL=Annuler
--------------------------------------------------------------------------------
/Source/Windows/Languages/German.txt:
--------------------------------------------------------------------------------
1 | # Main
2 | NEW_NOTE=Neue Notiz
3 | NOTES=Notizen
4 | TODAY=Heute
5 | YESTERDAY=Gestern
6 | DAYSAGO=Tage zurück
7 | SEARCH=Suche...
8 | SYNC=Synchronisieren
9 | DEV_SYNC_CONFIRM=Das Gerät "%s" fordert die Erlaubnis zur Synchronisierung an. Erlauben?
10 | CUT=Ausschneiden
11 | COPY=Kopieren
12 | PASTE=Einfügen
13 | LAST_UPDATE=Letztes Update:
14 |
15 | # Settings
16 | SETTINGS=Einstellungen
17 | INTERFACE=Benutzeroberfläche
18 | DARK_THEME=Dunkles Thema
19 | THEME_TIME=Thema basierend auf der Zeit
20 | DARK_THEME_START=Beginn des dunklen Themas:
21 | DARK_THEME_END=Ende des dunklen Themas:
22 | SYNCHRONIZATION=Synchronisierung
23 | SYNC_PORT=Port:
24 | SYNC_WITH_ANY_IPS=Synchronisierung mit beliebigen IPs (unsicher)
25 | ALLOW_IPS=Erlaubte IP-Adressen:
26 | ALLOW_DEVS=Erlaubte Geräte:
27 | ALLOW_DEV_REM=Entfernen
28 | ENTER_DEV_ID=Geben Sie die Geräte-ID ein
29 | BLOCK_REQUEST_NEW_DEVS=Anfragen neuer Geräte blockieren
30 | IMPORT=Importieren
31 | EXPORT=Exportieren
32 | CATEGORIES=Kategorien
33 | USER_CATEGORIES=#Einkäufe\n#Ideen\n#Arbeit\n#Projekte\n#Familie\n#Gesundheit\n#Finanzen\n#Studium\n#Reisen\n#Hobbys\n#Persönlich
34 | DONE=Fertig
35 | OK=OK
36 | CANCEL=Abbrechen
--------------------------------------------------------------------------------
/Source/Windows/Languages/Italian.txt:
--------------------------------------------------------------------------------
1 | # Main
2 | NEW_NOTE=Nuova nota
3 | NOTES=Note
4 | TODAY=Oggi
5 | YESTERDAY=Ieri
6 | DAYSAGO=giorni fa
7 | SEARCH=Cerca...
8 | SYNC=Sincronizza
9 | DEV_SYNC_CONFIRM=Il dispositivo "%s" richiede il permesso per sincronizzarsi. Permettere?
10 | CUT=Taglia
11 | COPY=Copia
12 | PASTE=Incolla
13 | LAST_UPDATE=Ultimo aggiornamento:
14 |
15 | # Settings
16 | SETTINGS=Impostazioni
17 | INTERFACE=Interfaccia
18 | DARK_THEME=Tema scuro
19 | THEME_TIME=Il tema è dipendente dall'orario
20 | DARK_THEME_START=Inizio tema scuro:
21 | DARK_THEME_END=Fine tema scuro:
22 | SYNCHRONIZATION=Sincronizzazione
23 | SYNC_PORT=Porta:
24 | SYNC_WITH_ANY_IPS=Sincronizzazione con qualsiasi IP (non sicuro)
25 | ALLOW_IPS=Indirizzi IP consentiti:
26 | ALLOW_DEVS=Dispositivi consentiti:
27 | ALLOW_DEV_REM=Rimuovi
28 | ENTER_DEV_ID=Inserisci l'ID del dispositivo
29 | BLOCK_REQUEST_NEW_DEVS=Blocca le richieste per nuovi dispositivi
30 | IMPORT=Importa
31 | EXPORT=Esporta
32 | CATEGORIES=Categorie
33 | USER_CATEGORIES=#Shopping\n#Idee\n#Lavoro\n#Progetti\n#Famiglia\n#Salute\n#Finanze\n#Studio\n#Viaggi\n#Hobby\n#Personale
34 | DONE=Fatto
35 | OK=OK
36 | CANCEL=Annulla
--------------------------------------------------------------------------------
/Source/Windows/Languages/Japanese.txt:
--------------------------------------------------------------------------------
1 | # Main
2 | NEW_NOTE=新しいノート
3 | NOTES=ノート
4 | TODAY=今日
5 | YESTERDAY=昨日
6 | DAYSAGO=日前
7 | SEARCH=検索...
8 | SYNC=同期
9 | DEV_SYNC_CONFIRM=「%s」デバイスが同期の許可を求めています。許可しますか?
10 | CUT=切り取り
11 | COPY=コピー
12 | PASTE=貼り付け
13 | LAST_UPDATE=最終更新:
14 |
15 | # Settings
16 | SETTINGS=設定
17 | INTERFACE=インターフェース
18 | DARK_THEME=ダークテーマ
19 | THEME_TIME=テーマは時間によって変わる
20 | DARK_THEME_START=ダークテーマ開始:
21 | DARK_THEME_END=ダークテーマ終了:
22 | SYNCHRONIZATION=同期
23 | SYNC_PORT=ポート:
24 | SYNC_WITH_ANY_IPS=任意のIPとの同期(セキュリティ非対応)
25 | ALLOW_IPS=許可されたIPアドレス:
26 | ALLOW_DEVS=許可されたデバイス:
27 | ALLOW_DEV_REM=デバイスを削除
28 | ENTER_DEV_ID=デバイスIDを入力
29 | BLOCK_REQUEST_NEW_DEVS=新しいデバイスのリクエストをブロック
30 | IMPORT=インポート
31 | EXPORT=エクスポート
32 | CATEGORIES=カテゴリ
33 | USER_CATEGORIES=#買い物\n#アイデア\n#仕事\n#プロジェクト\n#家族\n#健康\n#財務\n#勉強\n#旅行\n#趣味\n#個人的
34 | DONE=完了
35 | OK=OK
36 | CANCEL=キャンセル
--------------------------------------------------------------------------------
/Source/Windows/Languages/Korean.txt:
--------------------------------------------------------------------------------
1 | # Main
2 | NEW_NOTE=새로운 노트
3 | NOTES=노트
4 | TODAY=오늘
5 | YESTERDAY=어제
6 | DAYSAGO=일 전
7 | SEARCH=검색...
8 | SYNC=동기화
9 | DEV_SYNC_CONFIRM="%s" 장치가 동기화 권한을 요청합니다. 허용하시겠습니까?
10 | CUT=잘라내기
11 | COPY=복사
12 | PASTE=붙여넣기
13 | LAST_UPDATE=마지막 업데이트:
14 |
15 | # Settings
16 | SETTINGS=설정
17 | INTERFACE=인터페이스
18 | DARK_THEME=어두운 테마
19 | THEME_TIME=테마는 시간에 따라 달라짐
20 | DARK_THEME_START=어두운 테마 시작:
21 | DARK_THEME_END=어두운 테마 종료:
22 | SYNCHRONIZATION=동기화
23 | SYNC_PORT=포트:
24 | SYNC_WITH_ANY_IPS=모든 IP와 동기화 (보안되지 않음)
25 | ALLOW_IPS=허용된 IP 주소:
26 | ALLOW_DEVS=허용된 장치:
27 | ALLOW_DEV_REM=장치 제거
28 | ENTER_DEV_ID=장치 ID 입력
29 | BLOCK_REQUEST_NEW_DEVS=새로운 장치 요청 차단
30 | IMPORT=가져오기
31 | EXPORT=내보내기
32 | CATEGORIES=카테고리
33 | USER_CATEGORIES=#쇼핑\n#아이디어\n#일\n#프로젝트\n#가족\n#건강\n#재정\n#학습\n#여행\n#취미\n#개인
34 | DONE=완료
35 | OK=확인
36 | CANCEL=취소
--------------------------------------------------------------------------------
/Source/Windows/Languages/Portuguese.txt:
--------------------------------------------------------------------------------
1 | # Main
2 | NEW_NOTE=Nova nota
3 | NOTES=Notas
4 | TODAY=Hoje
5 | YESTERDAY=Ontem
6 | DAYSAGO=dias atrás
7 | SEARCH=Pesquisar...
8 | SYNC=Sincronizar
9 | DEV_SYNC_CONFIRM=O dispositivo "%s" solicita permissão para sincronizar. Permitir?
10 | CUT=Cortar
11 | COPY=Copiar
12 | PASTE=Colar
13 | LAST_UPDATE=Última atualização:
14 |
15 | # Settings
16 | SETTINGS=Configurações
17 | INTERFACE=Interface
18 | DARK_THEME=Tema escuro
19 | THEME_TIME=O tema depende da hora
20 | DARK_THEME_START=Início do tema escuro:
21 | DARK_THEME_END=Fim do tema escuro:
22 | SYNCHRONIZATION=Sincronização
23 | SYNC_PORT=Porta:
24 | SYNC_WITH_ANY_IPS=Sincronização com qualquer IP (não seguro)
25 | ALLOW_IPS=Endereços IP permitidos:
26 | ALLOW_DEVS=Dispositivos permitidos:
27 | ALLOW_DEV_REM=Remover
28 | ENTER_DEV_ID=Digite o ID do dispositivo
29 | BLOCK_REQUEST_NEW_DEVS=Bloquear solicitações para novos dispositivos
30 | IMPORT=Importar
31 | EXPORT=Exportar
32 | CATEGORIES=Categorias
33 | USER_CATEGORIES=#Compras\n#Ideias\n#Trabalho\n#Projetos\n#Família\n#Saúde\n#Finanças\n#Estudos\n#Viagens\n#Hobbies\n#Pessoal
34 | DONE=Feito
35 | OK=OK
36 | CANCEL=Cancelar
--------------------------------------------------------------------------------
/Source/Windows/Languages/Russian.txt:
--------------------------------------------------------------------------------
1 | # Main
2 | NEW_NOTE=Новая заметка
3 | NOTES=Заметки
4 | TODAY=Сегодня
5 | YESTERDAY=Вчера
6 | DAYSAGO=дн. назад
7 | SEARCH=Поиск...
8 | SYNC=Синхронизация
9 | DEV_SYNC_CONFIRM=Устройство "%s" запрашивает разрешение на синхронизацию. Разрешить?
10 | CUT=Вырезать
11 | COPY=Копировать
12 | PASTE=Вставить
13 | LAST_UPDATE=Последнее обновление:
14 |
15 | # Settings
16 | SETTINGS=Настройки
17 | INTERFACE=Интерфейс
18 | DARK_THEME=Тёмная тема
19 | THEME_TIME=Тема в зависимости от времени
20 | DARK_THEME_START=Начало тёмной темы:
21 | DARK_THEME_END=Конец тёмной темы:
22 | SYNCHRONIZATION=Синхронизация
23 | SYNC_PORT=Порт:
24 | SYNC_WITH_ANY_IPS=Синхронизация с любыми IP (небезопасно)
25 | ALLOW_IPS=Разрешённые IP адреса:
26 | ALLOW_DEVS=Разрешённые устройства:
27 | ALLOW_DEV_REM=Удалить
28 | ENTER_DEV_ID=Введите ID устройства
29 | BLOCK_REQUEST_NEW_DEVS=Блокировать запросы новых устройств
30 | IMPORT=Импорт
31 | EXPORT=Экспорт
32 | CATEGORIES=Категории
33 | USER_CATEGORIES=#Покупки\n#Идеи\n#Работа\n#Проекты\n#Семья\n#Здоровье\n#Финансы\n#Учеба\n#Путешествия\n#Хобби\n#Личное
34 | DONE=Готово
35 | OK=ОК
36 | CANCEL=Отмена
--------------------------------------------------------------------------------
/Source/Windows/Languages/Spanish.txt:
--------------------------------------------------------------------------------
1 | # Main
2 | NEW_NOTE=Nueva nota
3 | NOTES=Notas
4 | TODAY=Hoy
5 | YESTERDAY=Ayer
6 | DAYSAGO=Hace días
7 | SEARCH=Buscar...
8 | SYNC=Sincronizar
9 | DEV_SYNC_CONFIRM=El dispositivo "%s" solicita permiso para sincronizar. ¿Lo permites?
10 | CUT=Cortar
11 | COPY=Copiar
12 | PASTE=Pegar
13 | LAST_UPDATE=Última actualización:
14 |
15 | # Settings
16 | SETTINGS=Configuración
17 | INTERFACE=Interfaz
18 | DARK_THEME=Tema oscuro
19 | THEME_TIME=El tema depende del tiempo
20 | DARK_THEME_START=Inicio del tema oscuro:
21 | DARK_THEME_END=Fin del tema oscuro:
22 | SYNCHRONIZATION=Sincronización
23 | SYNC_PORT=Puerto:
24 | SYNC_WITH_ANY_IPS=Sincronización con cualquier IP (inseguro)
25 | ALLOW_IPS=Direcciones IP permitidas:
26 | ALLOW_DEVS=Dispositivos permitidos:
27 | ALLOW_DEV_REM=Eliminar
28 | ENTER_DEV_ID=Ingrese el ID del dispositivo
29 | BLOCK_REQUEST_NEW_DEVS=Bloquear nuevas solicitudes de dispositivos
30 | IMPORT=Importar
31 | EXPORT=Exportar
32 | CATEGORIES=Categorías
33 | USER_CATEGORIES=#Compras\n#Ideas\n#Trabajo\n#Proyectos\n#Familia\n#Salud\n#Finanzas\n#Estudios\n#Viajes\n#Aficiones\n#Personal
34 | DONE=Hecho
35 | OK=Aceptar
36 | CANCEL=Cancelar
37 |
--------------------------------------------------------------------------------
/Source/Windows/Project1.dpr:
--------------------------------------------------------------------------------
1 | program Project1;
2 |
3 | uses
4 | Vcl.Forms,
5 | Unit1 in 'Unit1.pas' {Main},
6 | Unit2 in 'Unit2.pas' {Settings};
7 |
8 | {$R *.res}
9 |
10 | begin
11 | Application.Initialize;
12 | Application.MainFormOnTaskbar := True;
13 | Application.CreateForm(TMain, Main);
14 | Application.CreateForm(TSettings, Settings);
15 | Application.Run;
16 | end.
17 |
--------------------------------------------------------------------------------
/Source/Windows/Project1.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Windows/Project1.res
--------------------------------------------------------------------------------
/Source/Windows/Project1_Icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Windows/Project1_Icon.ico
--------------------------------------------------------------------------------
/Source/Windows/SQLite3Utils.pas:
--------------------------------------------------------------------------------
1 | {*
2 | * SQLite for Delphi and FreePascal/Lazarus
3 | *
4 | * This unit contains miscellaneous utility functions.
5 | *
6 | * Copyright (c) 2013 Yuri Plashenkov
7 | *
8 | * MIT License
9 | *
10 | * Permission is hereby granted, free of charge, to any person obtaining a copy
11 | * of this software and associated documentation files (the "Software"), to deal
12 | * in the Software without restriction, including without limitation the rights
13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | * copies of the Software, and to permit persons to whom the Software is
15 | * furnished to do so, subject to the following conditions:
16 |
17 | * The above copyright notice and this permission notice shall be included in all
18 | * copies or substantial portions of the Software.
19 |
20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | * SOFTWARE.
27 | *}
28 |
29 | unit SQLite3Utils;
30 |
31 | {$IFDEF FPC}
32 | {$MODE DELPHI}
33 | {$ENDIF}
34 |
35 | interface
36 |
37 | function StrToUTF8(const S: WideString): AnsiString;
38 | function UTF8ToStr(const S: PAnsiChar; const Len: Integer = -1): WideString;
39 | function QuotedStr(const S: WideString): WideString;
40 | function FloatToSQLStr(Value: Extended): WideString;
41 |
42 | implementation
43 |
44 | uses
45 | {$IFNDEF FPC}Windows,{$ENDIF} SysUtils;
46 |
47 | function StrToUTF8(const S: WideString): AnsiString;
48 | begin
49 | Result := UTF8Encode(S);
50 | end;
51 |
52 | function UTF8ToStr(const S: PAnsiChar; const Len: Integer): WideString;
53 | var
54 | UTF8Str: AnsiString;
55 | begin
56 | if Len < 0 then
57 | begin
58 | Result := UTF8Decode(S);
59 | end
60 | else if Len > 0 then
61 | begin
62 | SetLength(UTF8Str, Len);
63 | Move(S^, UTF8Str[1], Len);
64 | Result := UTF8Decode(UTF8Str);
65 | end
66 | else Result := '';
67 | end;
68 |
69 | function QuotedStr(const S: WideString): WideString;
70 | const
71 | Quote = #39;
72 | var
73 | I: Integer;
74 | begin
75 | Result := S;
76 | for I := Length(Result) downto 1 do
77 | if Result[I] = Quote then Insert(Quote, Result, I);
78 | Result := Quote + Result + Quote;
79 | end;
80 |
81 | function FloatToSQLStr(Value: Extended): WideString;
82 | var
83 | FS: TFormatSettings;
84 | begin
85 | {$IFDEF FPC}
86 | FS := DefaultFormatSettings;
87 | {$ELSE}
88 | GetLocaleFormatSettings(GetThreadLocale, FS);
89 | {$ENDIF}
90 | FS.DecimalSeparator := '.';
91 | Result := FloatToStr(Value, FS);
92 | end;
93 |
94 | end.
95 |
--------------------------------------------------------------------------------
/Source/Windows/SQLite3Wrap.pas:
--------------------------------------------------------------------------------
1 | {*
2 | * SQLite for Delphi and FreePascal/Lazarus
3 | *
4 | * This unit contains easy-to-use object wrapper over SQLite3 API functions.
5 | *
6 | * Copyright (c) 2013 Yuri Plashenkov
7 | *
8 | * MIT License
9 | *
10 | * Permission is hereby granted, free of charge, to any person obtaining a copy
11 | * of this software and associated documentation files (the "Software"), to deal
12 | * in the Software without restriction, including without limitation the rights
13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | * copies of the Software, and to permit persons to whom the Software is
15 | * furnished to do so, subject to the following conditions:
16 |
17 | * The above copyright notice and this permission notice shall be included in all
18 | * copies or substantial portions of the Software.
19 |
20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | * SOFTWARE.
27 | *}
28 |
29 | unit SQLite3Wrap;
30 |
31 | {$IFDEF FPC}
32 | {$MODE DELPHI}
33 | {$ENDIF}
34 |
35 | interface
36 |
37 | uses
38 | SysUtils, Classes, SQLite3;
39 |
40 | type
41 | ESQLite3Error = class(Exception);
42 |
43 | TSQLite3Statement = class;
44 | TSQLite3BlobHandler = class;
45 |
46 | { TSQLite3Database class }
47 |
48 | TSQLite3Database = class(TObject)
49 | private
50 | FHandle: PSQLite3;
51 | FStatementList: TList;
52 | FBlobHandlerList: TList;
53 | FTransactionOpen: Boolean;
54 | procedure Check(const ErrCode: Integer);
55 | procedure CheckHandle;
56 | public
57 | constructor Create;
58 | destructor Destroy; override;
59 |
60 | procedure Open(const FileName: WideString; Flags: Integer = 0);
61 | procedure Close;
62 |
63 | procedure Execute(const SQL: WideString);
64 | function LastInsertRowID: Int64;
65 | function Prepare(const SQL: WideString): TSQLite3Statement;
66 | function BlobOpen(const Table, Column: WideString; const RowID: Int64; const WriteAccess: Boolean = True): TSQLite3BlobHandler;
67 |
68 | procedure BeginTransaction;
69 | procedure Commit;
70 | procedure Rollback;
71 |
72 | property Handle: PSQLite3 read FHandle;
73 | property TransactionOpen: Boolean read FTransactionOpen;
74 | end;
75 |
76 | { TSQLite3Statement class }
77 |
78 | TSQLite3Statement = class(TObject)
79 | private
80 | FHandle: PSQLite3Stmt;
81 | FOwnerDatabase: TSQLite3Database;
82 | function ParamIndexByName(const ParamName: WideString): Integer;
83 | public
84 | constructor Create(OwnerDatabase: TSQLite3Database; const SQL: WideString);
85 | destructor Destroy; override;
86 |
87 | procedure BindInt(const ParamIndex: Integer; const Value: Integer); overload;
88 | procedure BindInt64(const ParamIndex: Integer; const Value: Int64); overload;
89 | procedure BindDouble(const ParamIndex: Integer; const Value: Double); overload;
90 | procedure BindText(const ParamIndex: Integer; const Value: WideString); overload;
91 | procedure BindNull(const ParamIndex: Integer); overload;
92 | procedure BindBlob(const ParamIndex: Integer; Data: Pointer; const Size: Integer); overload;
93 | procedure BindZeroBlob(const ParamIndex: Integer; const Size: Integer); overload;
94 | procedure BindInt(const ParamName: WideString; const Value: Integer); overload;
95 | procedure BindInt64(const ParamName: WideString; const Value: Int64); overload;
96 | procedure BindDouble(const ParamName: WideString; const Value: Double); overload;
97 | procedure BindText(const ParamName: WideString; const Value: WideString); overload;
98 | procedure BindNull(const ParamName: WideString); overload;
99 | procedure BindBlob(const ParamName: WideString; Data: Pointer; const Size: Integer); overload;
100 | procedure BindZeroBlob(const ParamName: WideString; const Size: Integer); overload;
101 | procedure ClearBindings;
102 |
103 | function Step: Integer;
104 | procedure Reset;
105 | function StepAndReset: Integer;
106 |
107 | function ColumnCount: Integer;
108 | function ColumnName(const ColumnIndex: Integer): WideString;
109 | function ColumnType(const ColumnIndex: Integer): Integer;
110 | function ColumnInt(const ColumnIndex: Integer): Integer;
111 | function ColumnInt64(const ColumnIndex: Integer): Int64;
112 | function ColumnDouble(const ColumnIndex: Integer): Double;
113 | function ColumnText(const ColumnIndex: Integer): WideString;
114 | function ColumnBlob(const ColumnIndex: Integer): Pointer;
115 | function ColumnBytes(const ColumnIndex: Integer): Integer;
116 |
117 | property Handle: PSQLite3Stmt read FHandle;
118 | property OwnerDatabase: TSQLite3Database read FOwnerDatabase;
119 | end;
120 |
121 | { TSQLite3BlobHandler class }
122 |
123 | TSQLite3BlobHandler = class(TObject)
124 | private
125 | FHandle: PSQLite3Blob;
126 | FOwnerDatabase: TSQLite3Database;
127 | public
128 | constructor Create(OwnerDatabase: TSQLite3Database; const Table, Column: WideString; const RowID: Int64; const WriteAccess: Boolean = True);
129 | destructor Destroy; override;
130 |
131 | function Bytes: Integer;
132 | procedure Read(Buffer: Pointer; const Size, Offset: Integer);
133 | procedure Write(Buffer: Pointer; const Size, Offset: Integer);
134 |
135 | property Handle: PSQLite3Blob read FHandle;
136 | property OwnerDatabase: TSQLite3Database read FOwnerDatabase;
137 | end;
138 |
139 | implementation
140 |
141 | uses
142 | SQLite3Utils;
143 |
144 | resourcestring
145 | SErrorMessage = 'SQLite3 error: %s';
146 | SDatabaseNotConnected = 'SQLite3 error: database is not connected.';
147 | STransactionAlreadyOpen = 'Transaction is already opened.';
148 | SNoTransactionOpen = 'No transaction is open';
149 |
150 | { TSQLite3Database }
151 |
152 | procedure TSQLite3Database.BeginTransaction;
153 | begin
154 | if not FTransactionOpen then
155 | begin
156 | Execute('BEGIN TRANSACTION;');
157 | FTransactionOpen := True;
158 | end
159 | else
160 | raise ESQLite3Error.Create(STransactionAlreadyOpen);
161 | end;
162 |
163 | function TSQLite3Database.BlobOpen(const Table, Column: WideString;
164 | const RowID: Int64; const WriteAccess: Boolean): TSQLite3BlobHandler;
165 | begin
166 | Result := TSQLite3BlobHandler.Create(Self, Table, Column, RowID, WriteAccess);
167 | end;
168 |
169 | procedure TSQLite3Database.Check(const ErrCode: Integer);
170 | begin
171 | if ErrCode <> SQLITE_OK then
172 | raise ESQLite3Error.CreateFmt(SErrorMessage, [UTF8ToStr(sqlite3_errmsg(FHandle))]);
173 | end;
174 |
175 | procedure TSQLite3Database.CheckHandle;
176 | begin
177 | if FHandle = nil then
178 | raise ESQLite3Error.Create(SDatabaseNotConnected);
179 | end;
180 |
181 | procedure TSQLite3Database.Close;
182 | var
183 | I: Integer;
184 | begin
185 | if FHandle <> nil then
186 | begin
187 | if FTransactionOpen then
188 | Rollback;
189 | // Delete all statements
190 | for I := FStatementList.Count - 1 downto 0 do
191 | TSQLite3Statement(FStatementList[I]).Free;
192 | // Delete all blob handlers
193 | for I := FBlobHandlerList.Count - 1 downto 0 do
194 | TSQLite3BlobHandler(FBlobHandlerList[I]).Free;
195 | sqlite3_close(FHandle);
196 | FHandle := nil;
197 | end;
198 | end;
199 |
200 | procedure TSQLite3Database.Commit;
201 | begin
202 | if FTransactionOpen then
203 | begin
204 | Execute('COMMIT;');
205 | FTransactionOpen := False;
206 | end
207 | else
208 | raise ESQLite3Error.Create(SNoTransactionOpen);
209 | end;
210 |
211 | constructor TSQLite3Database.Create;
212 | begin
213 | FHandle := nil;
214 | FStatementList := TList.Create;
215 | FBlobHandlerList := TList.Create;
216 | end;
217 |
218 | destructor TSQLite3Database.Destroy;
219 | begin
220 | Close;
221 | FBlobHandlerList.Free;
222 | FStatementList.Free;
223 | inherited;
224 | end;
225 |
226 | procedure TSQLite3Database.Execute(const SQL: WideString);
227 | begin
228 | CheckHandle;
229 | Check(sqlite3_exec(FHandle, PAnsiChar(StrToUTF8(SQL)), nil, nil, nil));
230 | end;
231 |
232 | function TSQLite3Database.LastInsertRowID: Int64;
233 | begin
234 | CheckHandle;
235 | Result := sqlite3_last_insert_rowid(FHandle);
236 | end;
237 |
238 | procedure TSQLite3Database.Open(const FileName: WideString; Flags: Integer);
239 | begin
240 | Close;
241 | if Flags = 0 then
242 | Check(sqlite3_open(PAnsiChar(StrToUTF8(FileName)), FHandle))
243 | else
244 | Check(sqlite3_open_v2(PAnsiChar(StrToUTF8(FileName)), FHandle, Flags, nil));
245 | end;
246 |
247 | function TSQLite3Database.Prepare(const SQL: WideString): TSQLite3Statement;
248 | begin
249 | Result := TSQLite3Statement.Create(Self, SQL);
250 | end;
251 |
252 | procedure TSQLite3Database.Rollback;
253 | begin
254 | if FTransactionOpen then
255 | begin
256 | Execute('ROLLBACK;');
257 | FTransactionOpen := False;
258 | end
259 | else
260 | raise ESQLite3Error.Create(SNoTransactionOpen);
261 | end;
262 |
263 | { TSQLite3Statement }
264 |
265 | procedure TSQLite3Statement.BindBlob(const ParamIndex: Integer; Data: Pointer;
266 | const Size: Integer);
267 | begin
268 | FOwnerDatabase.Check(sqlite3_bind_blob(FHandle, ParamIndex, Data, Size, SQLITE_TRANSIENT));
269 | end;
270 |
271 | procedure TSQLite3Statement.BindDouble(const ParamIndex: Integer;
272 | const Value: Double);
273 | begin
274 | FOwnerDatabase.Check(sqlite3_bind_double(FHandle, ParamIndex, Value));
275 | end;
276 |
277 | procedure TSQLite3Statement.BindInt(const ParamIndex, Value: Integer);
278 | begin
279 | FOwnerDatabase.Check(sqlite3_bind_int(FHandle, ParamIndex, Value));
280 | end;
281 |
282 | procedure TSQLite3Statement.BindInt64(const ParamIndex: Integer;
283 | const Value: Int64);
284 | begin
285 | FOwnerDatabase.Check(sqlite3_bind_int64(FHandle, ParamIndex, Value));
286 | end;
287 |
288 | procedure TSQLite3Statement.BindNull(const ParamIndex: Integer);
289 | begin
290 | FOwnerDatabase.Check(sqlite3_bind_null(FHandle, ParamIndex));
291 | end;
292 |
293 | procedure TSQLite3Statement.BindText(const ParamIndex: Integer;
294 | const Value: WideString);
295 | var
296 | S: AnsiString; { UTF-8 string }
297 | begin
298 | S := StrToUTF8(Value);
299 | FOwnerDatabase.Check(
300 | sqlite3_bind_text(FHandle, ParamIndex, PAnsiChar(S), Length(S), SQLITE_TRANSIENT)
301 | );
302 | end;
303 |
304 | procedure TSQLite3Statement.BindZeroBlob(const ParamIndex, Size: Integer);
305 | begin
306 | FOwnerDatabase.Check(sqlite3_bind_zeroblob(FHandle, ParamIndex, Size));
307 | end;
308 |
309 | procedure TSQLite3Statement.ClearBindings;
310 | begin
311 | FOwnerDatabase.Check(sqlite3_clear_bindings(FHandle));
312 | end;
313 |
314 | function TSQLite3Statement.ColumnBlob(const ColumnIndex: Integer): Pointer;
315 | begin
316 | Result := sqlite3_column_blob(FHandle, ColumnIndex);
317 | end;
318 |
319 | function TSQLite3Statement.ColumnBytes(const ColumnIndex: Integer): Integer;
320 | begin
321 | Result := sqlite3_column_bytes(FHandle, ColumnIndex);
322 | end;
323 |
324 | function TSQLite3Statement.ColumnCount: Integer;
325 | begin
326 | Result := sqlite3_column_count(FHandle);
327 | end;
328 |
329 | function TSQLite3Statement.ColumnDouble(const ColumnIndex: Integer): Double;
330 | begin
331 | Result := sqlite3_column_double(FHandle, ColumnIndex);
332 | end;
333 |
334 | function TSQLite3Statement.ColumnInt(const ColumnIndex: Integer): Integer;
335 | begin
336 | Result := sqlite3_column_int(FHandle, ColumnIndex);
337 | end;
338 |
339 | function TSQLite3Statement.ColumnInt64(const ColumnIndex: Integer): Int64;
340 | begin
341 | Result := sqlite3_column_int64(FHandle, ColumnIndex);
342 | end;
343 |
344 | function TSQLite3Statement.ColumnName(const ColumnIndex: Integer): WideString;
345 | begin
346 | Result := UTF8ToStr(sqlite3_column_name(FHandle, ColumnIndex));
347 | end;
348 |
349 | function TSQLite3Statement.ColumnText(const ColumnIndex: Integer): WideString;
350 | var
351 | Len: Integer;
352 | begin
353 | Len := ColumnBytes(ColumnIndex);
354 | Result := UTF8ToStr(sqlite3_column_text(FHandle, ColumnIndex), Len);
355 | end;
356 |
357 | function TSQLite3Statement.ColumnType(const ColumnIndex: Integer): Integer;
358 | begin
359 | Result := sqlite3_column_type(FHandle, ColumnIndex);
360 | end;
361 |
362 | constructor TSQLite3Statement.Create(OwnerDatabase: TSQLite3Database;
363 | const SQL: WideString);
364 | begin
365 | FOwnerDatabase := OwnerDatabase;
366 | FOwnerDatabase.CheckHandle;
367 | FOwnerDatabase.Check(
368 | sqlite3_prepare_v2(FOwnerDatabase.Handle, PAnsiChar(StrToUTF8(SQL)), -1, FHandle, nil)
369 | );
370 | FOwnerDatabase.FStatementList.Add(Self);
371 | end;
372 |
373 | destructor TSQLite3Statement.Destroy;
374 | begin
375 | FOwnerDatabase.FStatementList.Remove(Self);
376 | sqlite3_finalize(FHandle);
377 | inherited;
378 | end;
379 |
380 | function TSQLite3Statement.ParamIndexByName(const ParamName: WideString): Integer;
381 | begin
382 | Result := sqlite3_bind_parameter_index(FHandle, PAnsiChar(StrToUTF8(ParamName)));
383 | end;
384 |
385 | procedure TSQLite3Statement.Reset;
386 | begin
387 | sqlite3_reset(FHandle);
388 | end;
389 |
390 | function TSQLite3Statement.Step: Integer;
391 | begin
392 | Result := sqlite3_step(FHandle);
393 | end;
394 |
395 | function TSQLite3Statement.StepAndReset: Integer;
396 | begin
397 | Result := Step;
398 | Reset;
399 | end;
400 |
401 | procedure TSQLite3Statement.BindBlob(const ParamName: WideString; Data: Pointer;
402 | const Size: Integer);
403 | begin
404 | BindBlob(ParamIndexByName(ParamName), Data, Size);
405 | end;
406 |
407 | procedure TSQLite3Statement.BindDouble(const ParamName: WideString;
408 | const Value: Double);
409 | begin
410 | BindDouble(ParamIndexByName(ParamName), Value);
411 | end;
412 |
413 | procedure TSQLite3Statement.BindInt(const ParamName: WideString;
414 | const Value: Integer);
415 | begin
416 | BindInt(ParamIndexByName(ParamName), Value);
417 | end;
418 |
419 | procedure TSQLite3Statement.BindInt64(const ParamName: WideString;
420 | const Value: Int64);
421 | begin
422 | BindInt64(ParamIndexByName(ParamName), Value);
423 | end;
424 |
425 | procedure TSQLite3Statement.BindNull(const ParamName: WideString);
426 | begin
427 | BindNull(ParamIndexByName(ParamName));
428 | end;
429 |
430 | procedure TSQLite3Statement.BindText(const ParamName, Value: WideString);
431 | begin
432 | BindText(ParamIndexByName(ParamName), Value);
433 | end;
434 |
435 | procedure TSQLite3Statement.BindZeroBlob(const ParamName: WideString;
436 | const Size: Integer);
437 | begin
438 | BindZeroBlob(ParamIndexByName(ParamName), Size);
439 | end;
440 |
441 | { TSQLite3BlobHandler }
442 |
443 | function TSQLite3BlobHandler.Bytes: Integer;
444 | begin
445 | Result := sqlite3_blob_bytes(FHandle);
446 | end;
447 |
448 | constructor TSQLite3BlobHandler.Create(OwnerDatabase: TSQLite3Database; const Table,
449 | Column: WideString; const RowID: Int64; const WriteAccess: Boolean);
450 | begin
451 | FOwnerDatabase := OwnerDatabase;
452 | FOwnerDatabase.CheckHandle;
453 | FOwnerDatabase.Check(
454 | sqlite3_blob_open(FOwnerDatabase.FHandle, 'main', PAnsiChar(StrToUTF8(Table)),
455 | PAnsiChar(StrToUTF8(Column)), RowID, Ord(WriteAccess), FHandle)
456 | );
457 | FOwnerDatabase.FBlobHandlerList.Add(Self);
458 | end;
459 |
460 | destructor TSQLite3BlobHandler.Destroy;
461 | begin
462 | FOwnerDatabase.FBlobHandlerList.Remove(Self);
463 | sqlite3_blob_close(FHandle);
464 | inherited;
465 | end;
466 |
467 | procedure TSQLite3BlobHandler.Read(Buffer: Pointer; const Size,
468 | Offset: Integer);
469 | begin
470 | FOwnerDatabase.Check(sqlite3_blob_read(FHandle, Buffer, Size, Offset));
471 | end;
472 |
473 | procedure TSQLite3BlobHandler.Write(Buffer: Pointer; const Size,
474 | Offset: Integer);
475 | begin
476 | FOwnerDatabase.Check(sqlite3_blob_write(FHandle, Buffer, Size, Offset));
477 | end;
478 |
479 | end.
480 |
--------------------------------------------------------------------------------
/Source/Windows/UI/darktheme.css:
--------------------------------------------------------------------------------
1 | /*DarkTheme*/
2 | body{background-color:#2a3035;
3 |
4 | scrollbar-arrow-color: #3a404a;
5 |
6 | scrollbar-track-color: #2a3035;
7 | scrollbar-base-color: #2a3035;
8 |
9 | scrollbar-3dlight-color: #3a404a;
10 | scrollbar-highlight-color: #3a404a;
11 | scrollbar-face-color: #3a404a;
12 | scrollbar-shadow-color: #3a404a;
13 | scrollbar-darkshadow-color: #3a404a;}
14 |
15 | #panel{background-color:#202329;}
16 | #meta{color:#787c81;}
17 | .sub-panel{width:calc(100% - 1px); height:40px; border-right:1px solid #202329;}
18 | .sub-panel #search-block input[type=text]{border: 1px solid #3a404a; background-color: #202329;}
19 |
20 | #list{color:#ededef;}
21 | #list #items{border-right: 1px solid #202329;}
22 | #list #items #note{border-bottom:1px solid #3a404a;}
23 | #list #items #note:hover{background-color:#202329;}
24 | #list #items #note #date{color:#787c81;}
25 |
26 | textarea{color:white;}
27 |
28 | #note-categories{
29 | color:#ededef;
30 | background-color:#202329;
31 | border: 1px solid #3a404a;
32 | }
33 | #note-categories #item{
34 | border-bottom:1px solid #3a404a;
35 | }
36 | #note-categories #item:hover{background-color:#2a3035;}
37 |
38 | #settings #items #item{background-color:#202329; color:white;}
39 | #settings #items #item{border:1px solid #3a404a; border-top:none;}
40 | #settings #items #item:first-child{border:1px solid #3a404a;}
41 | #settings input[type="text"],#settings input[type="number"]{background-color:#202329;color:white;}
42 | #settings .aboutbox{color:#787c81;}
43 |
44 | #notification{background-color:#202329; border-top:1px solid black; color:white;}
--------------------------------------------------------------------------------
/Source/Windows/UI/images/done.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Windows/UI/images/done.png
--------------------------------------------------------------------------------
/Source/Windows/UI/images/folders.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Windows/UI/images/folders.png
--------------------------------------------------------------------------------
/Source/Windows/UI/images/new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Windows/UI/images/new.png
--------------------------------------------------------------------------------
/Source/Windows/UI/images/rm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Windows/UI/images/rm.png
--------------------------------------------------------------------------------
/Source/Windows/UI/images/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Windows/UI/images/search.png
--------------------------------------------------------------------------------
/Source/Windows/UI/images/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Windows/UI/images/settings.png
--------------------------------------------------------------------------------
/Source/Windows/UI/main.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | EasyNotes UI Windows
6 |
7 |
81 |
82 |
146 |
147 |
148 |