├── 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 | [![EN](https://user-images.githubusercontent.com/9499881/33184537-7be87e86-d096-11e7-89bb-f3286f752bc6.png)](https://github.com/r57zone/EasyNotes/) 2 | [![RU](https://user-images.githubusercontent.com/9499881/27683795-5b0fbac6-5cd8-11e7-929c-057833e01fb1.png)](https://github.com/r57zone/EasyNotes/blob/master/README.RU.md) 3 | # EasyNotes 4 | ![](https://user-images.githubusercontent.com/9499881/100446367-1cd14000-30c8-11eb-8e82-335f134a8c95.png) 5 | 6 | Простые заметки для Windows, Android и iOS, с прямой локальной синхронизацией или синхронизацией с веб-сервером. Сервером может выступать как приложение для Windows (для синхронизации необходимо запускать его), так и ваш веб-сервер. Посмотреть API можно [здесь](https://github.com/r57zone/EasyNotes/blob/master/API.RU.md). 7 | 8 | ## Особенности 9 | Поддерживаются следующие языки: английский, русский, китайский (традиционный), испанский, португальский (бразильский португальский), французкий, немецкий, японский, арабский, итальянский и корейский. 10 | 11 | ![flag-united-kingdom](https://github.com/user-attachments/assets/8c03c9b8-d154-466f-b9c4-6ea60278d537) 12 | ![flag-russia](https://user-images.githubusercontent.com/9499881/27683795-5b0fbac6-5cd8-11e7-929c-057833e01fb1.png) 13 | ![flag-china](https://github.com/user-attachments/assets/16848591-2baf-4300-893b-b95d5249a34e) 14 | ![flag-spanish](https://github.com/user-attachments/assets/a892b7ce-d83f-4914-9c54-9ba16c9c9e38) 15 | ![flag-brazil](https://github.com/user-attachments/assets/f2544579-81df-43b4-94c5-59c569828182) 16 | ![flag-french](https://github.com/user-attachments/assets/57f54331-32a3-4146-823c-4aa85a4c6669) 17 | ![flag-germany](https://github.com/user-attachments/assets/11066aa3-7c0d-4507-9df1-cad00fe53fad) 18 | ![flag-japan](https://github.com/user-attachments/assets/37cfc183-4de7-4d5a-a698-0da1286a6ee1) 19 | ![flag-egypt](https://github.com/user-attachments/assets/44399d0f-f05f-4d44-a4ab-13b6d7ded087) 20 | ![flag-saudi-arabia](https://github.com/user-attachments/assets/07d7d133-5a21-4bde-8c37-c1ef3772ac91) 21 | ![flag-united-arab-emirates](https://github.com/user-attachments/assets/81d3b610-a2f4-44c9-b2ad-20e4d7cfb2b2) 22 | ![flag-italy](https://github.com/user-attachments/assets/692490d6-bc53-446f-99b8-bf2becb8ec0d) 23 | ![flag-north-korea](https://github.com/user-attachments/assets/5b315a3d-6ce0-4cbb-b7a3-133ef2bcb2c5) 24 | ![flag-south-korea](https://github.com/user-attachments/assets/ed3d3778-9193-444a-85fd-ac5dd7bc91c6) 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/8c27ae18-10ae-49f0-9be2-bad14172166c)](https://github.com/user-attachments/assets/36da3bcd-ac0d-474c-a733-dc70f4b035f7) 77 | [![](https://github.com/user-attachments/assets/868fa151-ce97-447a-b87e-a8b435e8b29b)](https://github.com/user-attachments/assets/33a7e206-ae5a-438d-b1c2-92a2b95070a5) 78 | 79 | ### Android / iOS 80 | [![UI](https://github.com/user-attachments/assets/3e241777-79cf-4cdc-ab20-b322a0d2f099)](https://github.com/user-attachments/assets/3e241777-79cf-4cdc-ab20-b322a0d2f099) 81 | [![HTML Viewer Q](https://github.com/user-attachments/assets/6496fda0-4566-4eae-80d6-0fb7fa1ae880)](https://github.com/user-attachments/assets/6496fda0-4566-4eae-80d6-0fb7fa1ae880) 82 | [![PWA / HTML app](https://github.com/user-attachments/assets/4cec5cb1-4bf8-4f9a-98e8-ce646bab1998)](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 | [![EN](https://user-images.githubusercontent.com/9499881/33184537-7be87e86-d096-11e7-89bb-f3286f752bc6.png)](https://github.com/r57zone/EasyNotes/) 2 | [![RU](https://user-images.githubusercontent.com/9499881/27683795-5b0fbac6-5cd8-11e7-929c-057833e01fb1.png)](https://github.com/r57zone/EasyNotes/blob/master/README.RU.md) 3 | ← Choose language | Выберите язык 4 | 5 | # EasyNotes 6 | ![](https://user-images.githubusercontent.com/9499881/100446367-1cd14000-30c8-11eb-8e82-335f134a8c95.png) 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 | ![flag-united-kingdom](https://github.com/user-attachments/assets/8c03c9b8-d154-466f-b9c4-6ea60278d537) 14 | ![flag-russia](https://user-images.githubusercontent.com/9499881/27683795-5b0fbac6-5cd8-11e7-929c-057833e01fb1.png) 15 | ![flag-china](https://github.com/user-attachments/assets/16848591-2baf-4300-893b-b95d5249a34e) 16 | ![flag-spanish](https://github.com/user-attachments/assets/a892b7ce-d83f-4914-9c54-9ba16c9c9e38) 17 | ![flag-brazil](https://github.com/user-attachments/assets/f2544579-81df-43b4-94c5-59c569828182) 18 | ![flag-french](https://github.com/user-attachments/assets/57f54331-32a3-4146-823c-4aa85a4c6669) 19 | ![flag-germany](https://github.com/user-attachments/assets/11066aa3-7c0d-4507-9df1-cad00fe53fad) 20 | ![flag-japan](https://github.com/user-attachments/assets/37cfc183-4de7-4d5a-a698-0da1286a6ee1) 21 | ![flag-egypt](https://github.com/user-attachments/assets/44399d0f-f05f-4d44-a4ab-13b6d7ded087) 22 | ![flag-saudi-arabia](https://github.com/user-attachments/assets/07d7d133-5a21-4bde-8c37-c1ef3772ac91) 23 | ![flag-united-arab-emirates](https://github.com/user-attachments/assets/81d3b610-a2f4-44c9-b2ad-20e4d7cfb2b2) 24 | ![flag-italy](https://github.com/user-attachments/assets/692490d6-bc53-446f-99b8-bf2becb8ec0d) 25 | ![flag-north-korea](https://github.com/user-attachments/assets/5b315a3d-6ce0-4cbb-b7a3-133ef2bcb2c5) 26 | ![flag-south-korea](https://github.com/user-attachments/assets/ed3d3778-9193-444a-85fd-ac5dd7bc91c6) 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/9195f448-6e8e-4e64-bf9d-7d346bb27d59)](https://github.com/user-attachments/assets/928a044c-921e-4780-aa4b-81c1ab86d89b) 79 | [![](https://github.com/user-attachments/assets/2fd0aed4-fddf-433b-8fe7-78a6759261bb)](https://github.com/user-attachments/assets/21b2a33c-13cd-44fd-a501-1be23a3d7d57) 80 | 81 | ### Android / iOS 82 | [![UI](https://github.com/user-attachments/assets/bbb6e01a-abe3-4b72-bcba-0817f3d88c06)](https://github.com/user-attachments/assets/bbb6e01a-abe3-4b72-bcba-0817f3d88c06) 83 | [![HTML Viewer Q](https://github.com/user-attachments/assets/a6988b94-1d23-4497-b5f6-6b46dc8e8115)](https://github.com/user-attachments/assets/a6988b94-1d23-4497-b5f6-6b46dc8e8115) 84 | [![PWA / HTML app](https://github.com/user-attachments/assets/f56a9649-6220-405e-a0e0-a021280c613b)](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 | 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'] . '' . "\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 |
149 |
150 |
151 |
152 |
Заметки (3)
153 |
154 | 155 |
156 |
157 |
158 |
Заголовок
159 |
28 сен. 2018
160 |
161 |
162 |
163 |
164 |
165 |
166 | 167 |
168 |
169 | 170 |
171 |
172 |
173 |
Заметка
174 |
175 |
176 |
177 |
3 дня назад
178 |
25 сент. 2:29
179 |
180 |
181 | 182 |
183 |
184 |
185 |
186 | 196 |
197 |
198 |
199 | 200 | -------------------------------------------------------------------------------- /Source/Windows/Unit1.dfm: -------------------------------------------------------------------------------- 1 | object Main: TMain 2 | Left = 0 3 | Top = 0 4 | ClientHeight = 400 5 | ClientWidth = 680 6 | Color = clBtnFace 7 | Font.Charset = DEFAULT_CHARSET 8 | Font.Color = clWindowText 9 | Font.Height = -12 10 | Font.Name = 'Segoe UI' 11 | Font.Style = [] 12 | Position = poScreenCenter 13 | OnActivate = FormActivate 14 | OnClose = FormClose 15 | OnCreate = FormCreate 16 | OnDeactivate = FormDeactivate 17 | TextHeight = 15 18 | object WebView: TWebBrowser 19 | Left = 0 20 | Top = 0 21 | Width = 680 22 | Height = 400 23 | Align = alClient 24 | TabOrder = 0 25 | OnBeforeNavigate2 = WebViewBeforeNavigate2 26 | OnDocumentComplete = WebViewDocumentComplete 27 | ExplicitWidth = 668 28 | ExplicitHeight = 397 29 | ControlData = { 30 | 4C00000048460000572900000000000000000000000000000000000000000000 31 | 000000004C000000000000000000000001000000E0D057007335CF11AE690800 32 | 2B2E126208000000000000004C0000000114020000000000C000000000000046 33 | 8000000000000000000000000000000000000000000000000000000000000000 34 | 00000000000000000100000000000000000000000000000000000000} 35 | end 36 | object IdHTTPServer: TIdHTTPServer 37 | Bindings = <> 38 | DefaultPort = 735 39 | OnCommandGet = IdHTTPServerCommandGet 40 | Left = 24 41 | Top = 8 42 | end 43 | object PopupMenu: TPopupMenu 44 | Left = 104 45 | Top = 8 46 | object CutBtn: TMenuItem 47 | Caption = #1042#1099#1088#1077#1079#1072#1090#1100 48 | OnClick = CutBtnClick 49 | end 50 | object CopyBtn: TMenuItem 51 | Caption = #1050#1086#1087#1080#1088#1086#1074#1072#1090#1100 52 | OnClick = CopyBtnClick 53 | end 54 | object PasteBtn: TMenuItem 55 | Caption = #1042#1089#1090#1072#1074#1080#1090#1100 56 | OnClick = PasteBtnClick 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /Source/Windows/Unit2.dfm: -------------------------------------------------------------------------------- 1 | object Settings: TSettings 2 | Left = 0 3 | Top = 0 4 | BorderIcons = [biSystemMenu, biMinimize] 5 | BorderStyle = bsSingle 6 | Caption = #1053#1072#1089#1090#1088#1086#1081#1082#1080 7 | ClientHeight = 386 8 | ClientWidth = 520 9 | Color = clBtnFace 10 | Font.Charset = DEFAULT_CHARSET 11 | Font.Color = clWindowText 12 | Font.Height = -12 13 | Font.Name = 'Segoe UI' 14 | Font.Style = [] 15 | Position = poScreenCenter 16 | OnCreate = FormCreate 17 | OnShow = FormShow 18 | TextHeight = 15 19 | object InterfaceGB: TGroupBox 20 | Left = 264 21 | Top = 8 22 | Width = 248 23 | Height = 122 24 | Caption = #1048#1085#1090#1077#1088#1092#1077#1081#1089 25 | TabOrder = 0 26 | object DarkThemeStartHourLbl: TLabel 27 | Left = 8 28 | Top = 65 29 | Width = 121 30 | Height = 15 31 | Caption = #1053#1072#1095#1072#1083#1086' '#1090#1105#1084#1085#1086#1081' '#1090#1077#1084#1099':' 32 | end 33 | object DarkThemeEndHourLbl: TLabel 34 | Left = 8 35 | Top = 95 36 | Width = 113 37 | Height = 15 38 | Caption = #1050#1086#1085#1077#1094' '#1090#1105#1084#1085#1086#1081' '#1090#1077#1084#1099':' 39 | end 40 | object DarkThemeCB: TCheckBox 41 | Left = 8 42 | Top = 20 43 | Width = 97 44 | Height = 17 45 | Caption = #1058#1105#1084#1085#1072#1103' '#1090#1077#1084#1072 46 | TabOrder = 0 47 | OnClick = DarkThemeCBClick 48 | end 49 | object ThemeTimeCB: TCheckBox 50 | Left = 8 51 | Top = 40 52 | Width = 201 53 | Height = 17 54 | Caption = #1058#1077#1084#1072' '#1074' '#1079#1072#1074#1080#1089#1080#1084#1086#1089#1090#1080' '#1086#1090' '#1074#1088#1077#1084#1077#1085#1080 55 | TabOrder = 1 56 | OnClick = ThemeTimeCBClick 57 | end 58 | object DarkThemeStartHourEdt: TEdit 59 | Left = 170 60 | Top = 63 61 | Width = 48 62 | Height = 23 63 | TabOrder = 2 64 | end 65 | object DarkThemeEndHourEdt: TEdit 66 | Left = 170 67 | Top = 92 68 | Width = 48 69 | Height = 23 70 | TabOrder = 3 71 | end 72 | end 73 | object SyncGB: TGroupBox 74 | Left = 9 75 | Top = 8 76 | Width = 248 77 | Height = 338 78 | Caption = #1057#1080#1085#1093#1088#1086#1085#1080#1079#1072#1094#1080#1103 79 | TabOrder = 1 80 | object PortLbl: TLabel 81 | Left = 8 82 | Top = 26 83 | Width = 31 84 | Height = 15 85 | Caption = #1055#1086#1088#1090':' 86 | end 87 | object AllowedIPsLbl: TLabel 88 | Left = 8 89 | Top = 92 90 | Width = 133 91 | Height = 15 92 | Caption = #1056#1072#1079#1088#1077#1096#1105#1085#1085#1099#1077' IP '#1072#1076#1088#1077#1089#1072':' 93 | end 94 | object AllowedDevsLbl: TLabel 95 | Left = 8 96 | Top = 184 97 | Width = 144 98 | Height = 15 99 | Caption = #1056#1072#1079#1088#1077#1096#1105#1085#1085#1099#1077' '#1091#1089#1090#1088#1086#1081#1089#1090#1074#1072':' 100 | end 101 | object PortEdt: TEdit 102 | Left = 56 103 | Top = 23 104 | Width = 48 105 | Height = 23 106 | TabOrder = 0 107 | end 108 | object AllowedIPsMemo: TMemo 109 | Left = 8 110 | Top = 113 111 | Width = 232 112 | Height = 65 113 | ScrollBars = ssVertical 114 | TabOrder = 2 115 | end 116 | object AllowAnyIPsCB: TCheckBox 117 | Left = 8 118 | Top = 52 119 | Width = 232 120 | Height = 34 121 | Caption = #1057#1080#1085#1093#1088#1086#1085#1080#1079#1072#1094#1080#1103' '#1089' '#1083#1102#1073#1099#1084#1080' IP ('#1085#1077#1073#1077#1079#1086#1087#1072#1089#1085#1086')' 122 | TabOrder = 1 123 | WordWrap = True 124 | OnClick = AllowAnyIPsCBClick 125 | end 126 | object AllowedDevsLB: TListBox 127 | Left = 8 128 | Top = 205 129 | Width = 232 130 | Height = 62 131 | ItemHeight = 15 132 | TabOrder = 3 133 | OnKeyDown = AllowedDevsLBKeyDown 134 | OnMouseDown = AllowedDevsLBMouseDown 135 | end 136 | object AddManualDev: TButton 137 | Left = 8 138 | Top = 273 139 | Width = 34 140 | Height = 17 141 | Caption = '+' 142 | TabOrder = 4 143 | OnClick = AddManualDevClick 144 | end 145 | object BlockReqNewDevsCB: TCheckBox 146 | Left = 8 147 | Top = 296 148 | Width = 232 149 | Height = 33 150 | Caption = #1041#1083#1086#1082#1080#1088#1086#1074#1072#1090#1100' '#1079#1072#1087#1088#1086#1089#1099' '#1085#1086#1074#1099#1093' '#1091#1089#1090#1088#1086#1081#1089#1090#1074 151 | TabOrder = 6 152 | WordWrap = True 153 | end 154 | object RemManualDev: TButton 155 | Left = 44 156 | Top = 273 157 | Width = 34 158 | Height = 17 159 | Caption = '-' 160 | TabOrder = 5 161 | OnClick = RemManualDevClick 162 | end 163 | end 164 | object OkBtn: TButton 165 | Left = 8 166 | Top = 353 167 | Width = 75 168 | Height = 25 169 | Caption = #1054#1050 170 | TabOrder = 2 171 | OnClick = OkBtnClick 172 | end 173 | object CancelBtn: TButton 174 | Left = 88 175 | Top = 353 176 | Width = 75 177 | Height = 25 178 | Caption = #1054#1090#1084#1077#1085#1072 179 | TabOrder = 3 180 | OnClick = CancelBtnClick 181 | end 182 | object AboutBtn: TButton 183 | Left = 488 184 | Top = 354 185 | Width = 25 186 | Height = 25 187 | Caption = '?' 188 | TabOrder = 4 189 | OnClick = AboutBtnClick 190 | end 191 | object NotesGB: TGroupBox 192 | Left = 264 193 | Top = 228 194 | Width = 248 195 | Height = 54 196 | Caption = #1047#1072#1084#1077#1090#1082#1080 197 | TabOrder = 5 198 | object ImportBtn: TButton 199 | Left = 8 200 | Top = 20 201 | Width = 75 202 | Height = 25 203 | Caption = #1048#1084#1087#1086#1088#1090 204 | TabOrder = 0 205 | OnClick = ImportBtnClick 206 | end 207 | object ExportBtn: TButton 208 | Left = 88 209 | Top = 20 210 | Width = 75 211 | Height = 25 212 | Caption = #1069#1082#1089#1087#1086#1088#1090 213 | TabOrder = 1 214 | OnClick = ExportBtnClick 215 | end 216 | end 217 | object CategoriesGB: TGroupBox 218 | Left = 263 219 | Top = 132 220 | Width = 249 221 | Height = 94 222 | Caption = #1050#1072#1090#1077#1075#1086#1088#1080#1080 223 | TabOrder = 6 224 | object CategoriesMemo: TMemo 225 | Left = 8 226 | Top = 20 227 | Width = 232 228 | Height = 65 229 | ScrollBars = ssVertical 230 | TabOrder = 0 231 | end 232 | end 233 | object AllowedDevsPM: TPopupMenu 234 | Left = 184 235 | Top = 216 236 | object AllowedDevRemBtn: TMenuItem 237 | Caption = #1059#1076#1072#1083#1080#1090#1100 238 | OnClick = AllowedDevRemBtnClick 239 | end 240 | end 241 | object OpenDialog: TOpenDialog 242 | Left = 288 243 | Top = 301 244 | end 245 | object SaveDialog: TSaveDialog 246 | Left = 360 247 | Top = 301 248 | end 249 | end 250 | -------------------------------------------------------------------------------- /Source/Windows/Unit2.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r57zone/EasyNotes/82bd50142a121aa1936ef90efd223c0682df8f05/Source/Windows/Unit2.pas -------------------------------------------------------------------------------- /Source/Windows/clear.bat: -------------------------------------------------------------------------------- 1 | del *.obj 2 | del *.dcu 3 | del Win32\Release\*.dcu 4 | del Win32\Debug\*.dcu 5 | rd /s /q __recovery 6 | rd /s /q __history 7 | del *.~* 8 | del *.hpp 9 | del *.dcp 10 | del *.dpl 11 | del *.cesettings 12 | del *.bak 13 | del *.dproj.local 14 | del *.identcache 15 | --del *.exe 16 | --del Win32\Release\*.exe 17 | --del Win32\Debug\*.exe -------------------------------------------------------------------------------- /Source/Windows/webapp/ReadMe.txt: -------------------------------------------------------------------------------- 1 | En: Multi version for iOS 9-12, but with app.manifest and . 2 | 3 | Ru: Multi версия для iOS 9-12, но с app.manifest и . --------------------------------------------------------------------------------