Compare commits

..

8 Commits

Author SHA1 Message Date
Jean-Baptiste
7822aeba56 [android] Use error in textfield instead alert dialog
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2026-01-01 21:53:49 +01:00
Jean-Baptiste
008a785564 [android] Update Android dependencies
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2026-01-01 07:21:26 +01:00
Jean-Baptiste
a62f9470ec Update copyright of the project
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2026-01-01 00:05:22 +01:00
zyphlar
bfe65e0de0 change date format
Signed-off-by: zyphlar <zyphlar@noreply.codeberg.org>
2025-12-31 19:31:51 +01:00
zyphlar
eee0401a66 update cdn setup for apache
Signed-off-by: zyphlar <zyphlar@noreply.codeberg.org>
2025-12-31 19:31:51 +01:00
Jean-Baptiste
4226e2f999 [android] Fix wrong text style
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-31 19:29:43 +01:00
ldcuof
94bcd5f366 [styles] Replace unpaved warning icon with new one
Signed-off-by: ldcuof <ldcuof@noreply.codeberg.org>
2025-12-31 19:28:43 +01:00
x7z4w
1b64151aee [cmake] Use default linker
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-12-31 19:12:27 +01:00
15 changed files with 158 additions and 193 deletions

View File

@@ -1,17 +1,13 @@
name: compare_subways name: process_subways
on: on:
workflow_dispatch: # Manual trigger workflow_dispatch: # Manual trigger
schedule:
# Run daily at 00:00 UTC
- cron: '0 0 * * *'
env: env:
#PLANET: /home/planet/planet/planet-latest.pbf PLANET: /home/planet/planet/planet.o5m
#TMPDIR: /tmp TMPDIR: /tmp
HTML_DIR: "/mnt/4tbexternal/osm-planet/subway/validator" HTML_DIR: "/mnt/4tbexternal/osm-planet/subway/validator"
#DUMP: "$HTML_DIR" DUMP: "$HTML_DIR"
#SKIP_PLANET_UPDATE: "1" SKIP_PLANET_UPDATE: "1"
SPREADSHEET_ID: "1SEW1-NiNOnA2qDwievcxYV1FOaQl1mb1fdeyqAxHu3k"
DEBIAN_FRONTEND: nonnteractive DEBIAN_FRONTEND: nonnteractive
TZ: Etc/UTC TZ: Etc/UTC
@@ -26,68 +22,20 @@ jobs:
volumes: volumes:
- /mnt/4tbexternal:/mnt/4tbexternal - /mnt/4tbexternal:/mnt/4tbexternal
concurrency: concurrency:
group: ${{ github.workflow }}-compare-subways-${{ github.event.pull_request.number || github.ref }} group: ${{ github.workflow }}-process-subways-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true cancel-in-progress: true
steps: steps:
- uses: actions/cache@v4 - uses: actions/cache@v4
with: with:
path: "~" path: "~"
key: cache-${{ github.run_id }}-${{ github.run_attempt }}} key: cache-${{ github.run_id }}-${{ github.run_attempt }}
- name: Checkout main repo - name: Checkout subways repo
shell: bash
run: |
echo "Cloning $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY branch $FORGEJO_REF_NAME"
cd ~
git clone --depth 1 --recurse-submodules --shallow-submodules -b $FORGEJO_REF_NAME --single-branch $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY.git comaps
- name: Checkout subways repo (TODO zy-fix-validation)
shell: bash shell: bash
run: | run: |
cd ~ cd ~
git clone --depth 1 --single-branch https://codeberg.org/comaps/subways.git git clone --depth 1 --single-branch https://codeberg.org/comaps/subways.git
update-planet-pbf:
name: Update PBF Planet
runs-on: mapfilemaker
container:
image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes:
- /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet
concurrency:
group: ${{ github.workflow }}-compare-subways-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- name: Download Planet File if Absent
shell: bash
# TODO: replace wget2 with curl -Z
run: |
if [ ! -d /home/planet/planet/ ]; then
mkdir -p /home/planet/planet/
fi
if [ ! -f /home/planet/planet/planet-latest.osm.pbf ]; then
cd /home/planet/planet/
wget2 --verbose --progress=bar --continue https://ftpmirror.your.org/pub/openstreetmap/pbf/planet-latest.osm.pbf
else
echo "planet-latest.osm.pbf was found, raw download not required."
fi
- name: Update PBF Planet
shell: bash
run: |
cd /home/planet/planet/
rm -f planet-latest-new.osm.pbf
pyosmium-up-to-date planet-latest.osm.pbf -o planet-latest-new.osm.pbf -v --size 16384
mv planet-latest-new.osm.pbf planet-latest.osm.pbf
- name: Notify Zulip
run: |
curl -X POST https://comaps.zulipchat.com/api/v1/messages \
-u $ZULIP_BOT_EMAIL:$ZULIP_API_KEY \
--data-urlencode type=stream \
--data-urlencode 'to="DevOps"' \
--data-urlencode topic=codeberg-bot \
--data-urlencode 'content=PBF planet update is done!'
update-planet-o5m: update-planet-o5m:
if: false
name: Update O5M Planet name: Update O5M Planet
runs-on: mapfilemaker runs-on: mapfilemaker
container: container:
@@ -96,7 +44,7 @@ jobs:
- /mnt/4tbexternal/:/mnt/4tbexternal/ - /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet - /mnt/4tbexternal/osm-planet:/home/planet
concurrency: concurrency:
group: ${{ github.workflow }}-compare-subways-${{ github.event.pull_request.number || github.ref }} group: ${{ github.workflow }}-process-subways-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true cancel-in-progress: true
steps: steps:
- name: Check for O5M Planet File - name: Check for O5M Planet File
@@ -134,8 +82,9 @@ jobs:
--data-urlencode topic=codeberg-bot \ --data-urlencode topic=codeberg-bot \
--data-urlencode 'content=O5M planet update is done!' --data-urlencode 'content=O5M planet update is done!'
compare-subways: update-subways:
name: Compare Subways if: inputs.run-subways
name: Update Subways
runs-on: mapfilemaker runs-on: mapfilemaker
needs: needs:
- clone-repos - clone-repos
@@ -145,19 +94,31 @@ jobs:
- /mnt/4tbexternal/:/mnt/4tbexternal/ - /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet - /mnt/4tbexternal/osm-planet:/home/planet
concurrency: concurrency:
group: ${{ github.workflow }}-compare-subways-${{ github.event.pull_request.number || github.ref }} group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true cancel-in-progress: true
steps: steps:
- uses: actions/cache@v4 - uses: actions/cache@v4
with: with:
path: "~" path: "~"
key: cache-${{ github.run_id }}-${{ github.run_attempt }} key: cache-${{ github.run_id }}-${{ github.run_attempt }}
- name: Compare Subways - name: Update Subways
shell: bash shell: bash
run: | run: |
cd ~/comaps/ cd ~/comaps/
cp tools/unix/maps/settings.sh.prod tools/unix/maps/settings.sh cp tools/unix/maps/settings.sh.prod tools/unix/maps/settings.sh
./tools/unix/maps/generate_subways.sh ./tools/unix/maps/generate_subways.sh
- name: Compare with VK validation
shell: bash
run: |
cd ~/subways
if [ -f "$HTML_DIR/index.html" ]; then
echo "Comparing local validation with VK's validation..."
python3 ./scripts/compare_html_validation.py "$HTML_DIR/index.html" \
--vk-url "https://maps.vk.com/osm/tools/subways/latest/index.html"
else
echo "Local index.html not found at $HTML_DIR/index.html"
exit 1
fi
- name: Notify Zulip - name: Notify Zulip
run: | run: |
curl -X POST https://comaps.zulipchat.com/api/v1/messages \ curl -X POST https://comaps.zulipchat.com/api/v1/messages \
@@ -166,46 +127,3 @@ jobs:
--data-urlencode 'to="DevOps"' \ --data-urlencode 'to="DevOps"' \
--data-urlencode topic=codeberg-bot \ --data-urlencode topic=codeberg-bot \
--data-urlencode 'content=Subways are done!' --data-urlencode 'content=Subways are done!'
- name: Compare with VK validation
shell: bash
run: |
cd ~/subways
if [ -f "$HTML_DIR/cities.txt" ]; then
echo "Comparing local validation with VK's validation..."
python3 ./scripts/compare_html_validation.py "$HTML_DIR/cities.txt" \
--remote-url "https://maps.vk.com/osm/tools/subways/latest/cities.txt"
else
echo "Local cities.txt not found at $HTML_DIR/cities.txt"
exit 1
fi
- name: Compare Google Sheets Data
shell: bash
run: |
set -e
# Download the Google Sheets data
GOOGLE_SHEETS_URL="https://docs.google.com/spreadsheets/d/${SPREADSHEET_ID}/export?format=csv"
echo "Downloading Google Sheets data from: $GOOGLE_SHEETS_URL"
curl -sL "$GOOGLE_SHEETS_URL" -o /tmp/google_sheets.csv
# Normalize line endings to avoid spurious diffs
sed 's/\r$//' source_data/Rapid.csv > /tmp/local_normalized.csv
sed 's/\r$//' /tmp/google_sheets.csv > /tmp/google_normalized.csv
# Generate unified diff
echo ""
echo "Differences between local Rapid.csv and Google Sheets:"
echo ""
if diff -u /tmp/local_normalized.csv /tmp/google_normalized.csv > /tmp/full_diff.txt; then
echo "No differences found! Local Rapid.csv is in sync with Google Sheets."
exit 0
else
cat /tmp/full_diff.txt
echo ""
echo "The above diff can be saved as a patch and applied with:"
echo " patch source_data/Rapid.csv < patch-file"
echo "or by manually reviewing and applying the changes."
exit 1
fi

View File

@@ -116,20 +116,6 @@ endif()
message(STATUS "Build type: " ${CMAKE_BUILD_TYPE}) message(STATUS "Build type: " ${CMAKE_BUILD_TYPE})
if (PLATFORM_LINUX OR PLATFORM_ANDROID)
find_program(LLD_FOUND ld.lld)
if (LLD_FOUND)
message(STATUS "Using ld.lld linker")
set(CMAKE_EXE_LINKER_FLAGS "-fuse-ld=lld")
else()
find_program(GOLD_FOUND ld.gold)
if (GOLD_FOUND)
message(STATUS "Using ld.gold")
set(CMAKE_EXE_LINKER_FLAGS "-fuse-ld=gold")
endif()
endif()
endif()
if (NOT SKIP_TESTS) if (NOT SKIP_TESTS)
enable_testing() enable_testing()
# Enables ctest -T memcheck with valgrind # Enables ctest -T memcheck with valgrind

2
NOTICE
View File

@@ -1,6 +1,6 @@
Copyright 2020 My.com B.V. (Mail.Ru Group) Copyright 2020 My.com B.V. (Mail.Ru Group)
Copyright 2025 Organic Maps Contributors Copyright 2025 Organic Maps Contributors
Copyright 2025 CoMaps Contributors Copyright 2026 CoMaps Contributors
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@@ -351,6 +351,7 @@ dependencies {
implementation libs.androidx.recyclerview implementation libs.androidx.recyclerview
implementation libs.androidx.work.runtime implementation libs.androidx.work.runtime
implementation libs.androidx.lifecycle.process implementation libs.androidx.lifecycle.process
implementation libs.androidx.documentfile
implementation libs.android.material implementation libs.android.material
// Fix for app/organicmaps/util/FileUploadWorker.java:14: error: cannot access ListenableFuture // Fix for app/organicmaps/util/FileUploadWorker.java:14: error: cannot access ListenableFuture
// https://github.com/organicmaps/organicmaps/issues/6106 // https://github.com/organicmaps/organicmaps/issues/6106

View File

@@ -16,8 +16,7 @@ import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager; import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.util.InputUtils; import app.organicmaps.util.InputUtils;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.button.MaterialButton;
import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.textfield.TextInputEditText; import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout; import com.google.android.material.textfield.TextInputLayout;
import java.util.Objects; import java.util.Objects;
@@ -38,7 +37,7 @@ public class BookmarkCategorySettingsFragment extends BaseMwmToolbarFragment
@NonNull @NonNull
private TextInputEditText mEditCategoryNameView; private TextInputEditText mEditCategoryNameView;
@NonNull @NonNull
private ShapeableImageView mSaveView; private MaterialButton mSaveView;
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) public void onCreate(@Nullable Bundle savedInstanceState)
@@ -75,12 +74,32 @@ public class BookmarkCategorySettingsFragment extends BaseMwmToolbarFragment
@Override @Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) public void onTextChanged(CharSequence charSequence, int i, int i1, int i2)
{ {
clearNameBtn.setEndIconVisible(charSequence.length() > 0); if (charSequence.length() >= 1)
{
clearNameBtn.setEndIconVisible(true);
mSaveView.setEnabled(true);
}
else
{
clearNameBtn.setEndIconVisible(false);
mSaveView.setEnabled(false);
mEditCategoryNameView.setError(getString(R.string.bookmarks_error_title_empty_list_name));
}
} }
@Override @Override
public void afterTextChanged(Editable editable) public void afterTextChanged(Editable editable)
{} {
if (BookmarkManager.INSTANCE.isUsedCategoryName(getEditableCategoryName()) && !TextUtils.equals(getEditableCategoryName(), mCategory.getName()))
{
mEditCategoryNameView.setError(getString(R.string.bookmarks_error_title_list_name_already_taken));
mSaveView.setEnabled(false);
}
else
{
mSaveView.setEnabled(true);
}
}
}); });
mEditDescView = root.findViewById(R.id.edit_description); mEditDescView = root.findViewById(R.id.edit_description);
mEditDescView.setText(mCategory.getDescription()); mEditDescView.setText(mCategory.getDescription());
@@ -91,8 +110,6 @@ public class BookmarkCategorySettingsFragment extends BaseMwmToolbarFragment
private void onEditDoneClicked() private void onEditDoneClicked()
{ {
final String newCategoryName = getEditableCategoryName(); final String newCategoryName = getEditableCategoryName();
if (!validateCategoryName(newCategoryName))
return;
if (isCategoryNameChanged()) if (isCategoryNameChanged())
BookmarkManager.INSTANCE.setCategoryName(mCategory.getId(), newCategoryName); BookmarkManager.INSTANCE.setCategoryName(mCategory.getId(), newCategoryName);
@@ -109,30 +126,6 @@ public class BookmarkCategorySettingsFragment extends BaseMwmToolbarFragment
return !TextUtils.equals(categoryName, mCategory.getName()); return !TextUtils.equals(categoryName, mCategory.getName());
} }
private boolean validateCategoryName(@Nullable String name)
{
if (TextUtils.isEmpty(name))
{
new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setTitle(R.string.bookmarks_error_title_empty_list_name)
.setMessage(R.string.bookmarks_error_message_empty_list_name)
.setPositiveButton(R.string.ok, null)
.show();
return false;
}
if (BookmarkManager.INSTANCE.isUsedCategoryName(name) && !TextUtils.equals(name, mCategory.getName()))
{
new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setTitle(R.string.bookmarks_error_title_list_name_already_taken)
.setMessage(R.string.bookmarks_error_message_list_name_already_taken)
.setPositiveButton(R.string.ok, null)
.show();
return false;
}
return true;
}
@NonNull @NonNull
private String getEditableCategoryName() private String getEditableCategoryName()
{ {

View File

@@ -27,7 +27,7 @@
android:layout_marginTop="@dimen/margin_base"> android:layout_marginTop="@dimen/margin_base">
<RadioButton <RadioButton
style="@style/TextAppearance.Subtitle1" style="@style/MwmTextAppearance.Subtitle1"
android:id="@+id/sort_by_default" android:id="@+id/sort_by_default"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@@ -12,13 +12,15 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:theme="@style/MwmWidget.ToolbarTheme"> android:theme="@style/MwmWidget.ToolbarTheme">
<com.google.android.material.imageview.ShapeableImageView <com.google.android.material.button.MaterialButton
android:id="@+id/save" android:id="@+id/save"
android:layout_width="?actionBarSize" android:layout_width="?actionBarSize"
android:layout_height="?actionBarSize" android:layout_height="?actionBarSize"
android:scaleType="centerInside"
android:layout_gravity="end|center_vertical" android:layout_gravity="end|center_vertical"
app:srcCompat="@drawable/ic_done"/> app:icon="@drawable/ic_done"
app:iconGravity="textStart"
app:iconPadding="0dp"
app:iconSize="24dp" />
</com.google.android.material.appbar.MaterialToolbar> </com.google.android.material.appbar.MaterialToolbar>
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:scrollbars="none" android:scrollbars="none"

View File

@@ -1,15 +1,15 @@
[versions] [versions]
androidGradlePlugin = "8.11.2" androidGradlePlugin = "8.13.2"
androidxCarApp = "1.7.0" androidxCarApp = "1.7.0"
[libraries] [libraries]
android-tools = { module = "com.android.tools.build:gradle", version.ref = "androidGradlePlugin" } android-tools = { module = "com.android.tools.build:gradle", version.ref = "androidGradlePlugin" }
triplet-play-publisher = { module = "com.github.triplet.gradle:play-publisher", version = "3.12.1" } triplet-play-publisher = { module = "com.github.triplet.gradle:play-publisher", version = "3.13.0" }
huawei-publish = { module = "ru.cian:huawei-publish-gradle-plugin", version = "1.4.2" } huawei-publish = { module = "ru.cian:huawei-publish-gradle-plugin", version = "1.4.2" }
android-tools-desugar = { module = "com.android.tools:desugar_jdk_libs", version = "2.1.5" } android-tools-desugar = { module = "com.android.tools:desugar_jdk_libs", version = "2.1.5" }
microg-services-location = { module = "org.microg.gms:play-services-location", version = "0.3.6.244735" } microg-services-location = { module = "org.microg.gms:play-services-location", version = "0.3.6.244735" }
androidx-core = { module = "androidx.core:core", version = "1.17.0" } androidx-core = { module = "androidx.core:core", version = "1.17.0" }
jetbrains-kotlin-bom = { module = "org.jetbrains.kotlin:kotlin-bom", version = "2.2.20" } jetbrains-kotlin-bom = { module = "org.jetbrains.kotlin:kotlin-bom", version = "2.2.21" }
androidx-annotation = { module = "androidx.annotation:annotation", version = "1.9.1" } androidx-annotation = { module = "androidx.annotation:annotation", version = "1.9.1" }
androidx-appcompat = { module = "androidx.appcompat:appcompat", version = "1.7.1" } androidx-appcompat = { module = "androidx.appcompat:appcompat", version = "1.7.1" }
androidx-car-app = { module = "androidx.car.app:app", version.ref = "androidxCarApp" } androidx-car-app = { module = "androidx.car.app:app", version.ref = "androidxCarApp" }
@@ -21,12 +21,13 @@ androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version
androidx-work-runtime = { module = "androidx.work:work-runtime", version = "2.10.5" } androidx-work-runtime = { module = "androidx.work:work-runtime", version = "2.10.5" }
androidx-lifecycle-process = { module = "androidx.lifecycle:lifecycle-process", version = "2.9.4" } androidx-lifecycle-process = { module = "androidx.lifecycle:lifecycle-process", version = "2.9.4" }
androidx-media = { module = "androidx.media:media", version = "1.7.1" } androidx-media = { module = "androidx.media:media", version = "1.7.1" }
androidx-documentfile= { module = "androidx.documentfile:documentfile", version ="1.1.0" }
android-material = { module = "com.google.android.material:material", version = "1.12.0" } android-material = { module = "com.google.android.material:material", version = "1.12.0" }
google-guava = { module = "com.google.guava:guava", version = "33.4.8-android" } google-guava = { module = "com.google.guava:guava", version = "33.5.0-android" }
appdevnext-androidchart = { module = "com.github.AppDevNext:AndroidChart", version = "3.1.0.31" } appdevnext-androidchart = { module = "com.github.AppDevNext:AndroidChart", version = "3.1.0.31" }
androidx-test-junit = { module = "androidx.test.ext:junit", version = "1.3.0" } androidx-test-junit = { module = "androidx.test.ext:junit", version = "1.3.0" }
junit = { module = "junit:junit", version = "4.13.2" } junit = { module = "junit:junit", version = "4.13.2" }
mockito-core = { module = "org.mockito:mockito-core", version = "5.20.0" } mockito-core = { module = "org.mockito:mockito-core", version = "5.21.0" }
[plugins] [plugins]
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }

View File

@@ -126,6 +126,7 @@ dependencies {
implementation libs.androidx.recyclerview implementation libs.androidx.recyclerview
implementation libs.androidx.preference implementation libs.androidx.preference
implementation libs.android.material implementation libs.android.material
implementation libs.androidx.documentfile
testImplementation libs.junit testImplementation libs.junit
} }

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="26" height="33" version="1.1" viewBox="0 0 26 33" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="linearGradient1" x1="13" x2="13" y1="1" y2="30" gradientUnits="userSpaceOnUse">
<stop stop-color="#e8514e" offset="0"/>
<stop stop-color="#cc3633" offset="1"/>
</linearGradient>
<filter id="filter1" x="-.0882" y="-.441" width="1.1764" height="1.882" color-interpolation-filters="sRGB">
<feGaussianBlur stdDeviation="0.55125"/>
</filter>
</defs>
<ellipse cx="13" cy="30.177" rx="7.5" ry="1.5" filter="url(#filter1)" opacity=".1" stroke-linecap="round" stroke-linejoin="round"/>
<path d="m13 1c-6.3513 0-11.5 5.1487-11.5 11.5 2.4e-4 4.6124 2.7473 8.7238 6.8871 10.534 0.76685 0.33537 1.7261 1.1233 2.097 1.8742l2.5159 5.0935 2.5159-5.0935c0.37091-0.75091 1.3301-1.5388 2.0969-1.8742 4.1398-1.8104 6.8869-5.9219 6.8871-10.534 0-6.3513-5.1487-11.5-11.5-11.5z" fill="url(#linearGradient1)" stroke="#fff" stroke-linejoin="round" stroke-width="2"/>
<path d="m11.91 13.481-0.31705-4.7458q-0.08917-1.3871-0.08917-1.9915 0-0.82234 0.42603-1.2781 0.43594-0.46566 1.1394-0.46566 0.85206 0 1.1394 0.59446 0.28732 0.58456 0.28732 1.6942 0 0.65391-0.06935 1.3276l-0.42603 4.8845q-0.06935 0.87188-0.29723 1.3375-0.22788 0.46566-0.75299 0.46566-0.53502 0-0.74308-0.44585-0.20806-0.45576-0.29724-1.3772zm1.0998 6.5193q-0.60437 0-1.0601-0.3864-0.44585-0.39631-0.44585-1.0998 0-0.61428 0.42603-1.0403 0.43594-0.43594 1.0601-0.43594t1.0601 0.43594q0.44585 0.42603 0.44585 1.0403 0 0.69354-0.44585 1.0898-0.44585 0.39631-1.0403 0.39631z" fill="#fff" aria-label="!" data-font-family="Arial Rounded MT Bold"/>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1,15 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" width="26" height="33" viewBox="0 0 26 33">
<svg width="26" height="33" version="1.1" viewBox="0 0 26 33" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
<defs> <defs>
<linearGradient id="linearGradient1" x1="13" x2="13" y1="1" y2="30" gradientUnits="userSpaceOnUse"> <linearGradient id="a" x1="13" x2="13" y1="1" y2="30" gradientUnits="userSpaceOnUse">
<stop stop-color="#e8514e" offset="0"/> <stop offset="0" stop-color="#e8514e"/>
<stop stop-color="#cc3633" offset="1"/> <stop offset="1" stop-color="#cc3633"/>
</linearGradient> </linearGradient>
<filter id="filter1" x="-.0882" y="-.441" width="1.1764" height="1.882" color-interpolation-filters="sRGB"> <linearGradient xlink:href="#a" id="d" x1="13" x2="13" y1="1" y2="30" gradientTransform="translate(.122 .703)" gradientUnits="userSpaceOnUse"/>
<feGaussianBlur stdDeviation="0.55125"/> <filter id="b" width="1.176" height="1.882" x="-.088" y="-.441" color-interpolation-filters="sRGB">
<feGaussianBlur stdDeviation=".551"/>
</filter> </filter>
</defs> <filter id="c" width="1.176" height="1.882" x="-.088" y="-.441" color-interpolation-filters="sRGB">
<ellipse cx="13" cy="30.177" rx="7.5" ry="1.5" filter="url(#filter1)" opacity=".1" stroke-linecap="round" stroke-linejoin="round"/> <feGaussianBlur stdDeviation=".551"/>
<path d="m13 1c-6.3513 0-11.5 5.1487-11.5 11.5 2.4e-4 4.6124 2.7473 8.7238 6.8871 10.534 0.76685 0.33537 1.7261 1.1233 2.097 1.8742l2.5159 5.0935 2.5159-5.0935c0.37091-0.75091 1.3301-1.5388 2.0969-1.8742 4.1398-1.8104 6.8869-5.9219 6.8871-10.534 0-6.3513-5.1487-11.5-11.5-11.5z" fill="url(#linearGradient1)" stroke="#fff" stroke-linejoin="round" stroke-width="2"/> </filter>
<path d="m11.91 13.481-0.31705-4.7458q-0.08917-1.3871-0.08917-1.9915 0-0.82234 0.42603-1.2781 0.43594-0.46566 1.1394-0.46566 0.85206 0 1.1394 0.59446 0.28732 0.58456 0.28732 1.6942 0 0.65391-0.06935 1.3276l-0.42603 4.8845q-0.06935 0.87188-0.29723 1.3375-0.22788 0.46566-0.75299 0.46566-0.53502 0-0.74308-0.44585-0.20806-0.45576-0.29724-1.3772zm1.0998 6.5193q-0.60437 0-1.0601-0.3864-0.44585-0.39631-0.44585-1.0998 0-0.61428 0.42603-1.0403 0.43594-0.43594 1.0601-0.43594t1.0601 0.43594q0.44585 0.42603 0.44585 1.0403 0 0.69354-0.44585 1.0898-0.44585 0.39631-1.0403 0.39631z" fill="#fff" aria-label="!" data-font-family="Arial Rounded MT Bold"/> </defs>
<ellipse cx="13.122" cy="30.88" filter="url(#b)" opacity=".1" rx="7.5" ry="1.5" style="filter:url(#c)"/>
<path fill="url(#a)" stroke="#000" stroke-linejoin="round" stroke-width="2" d="M13.122 1.703c-6.352 0-11.5 5.149-11.5 11.5a11.5 11.5 0 0 0 6.887 10.534c.766.335 1.726 1.123 2.097 1.874l2.516 5.094 2.515-5.094c.371-.75 1.33-1.539 2.097-1.874a11.5 11.5 0 0 0 6.887-10.534c0-6.351-5.148-11.5-11.5-11.5z" style="fill:url(#d)"/>
<path d="M17.228 10.192v3.071h1.198v-3.071ZM17.228 7.424v1.721h1.198V7.423ZM7.088 10.192v3.071h1.198v-3.071ZM7.088 7.424v1.721h1.198V7.423Z" style="fill:#000;stroke-width:1.19817;stroke-linecap:square;stroke-linejoin:round" transform="translate(.365 -.337)"/>
<path d="m34.133 11.683-2.257-.84.1-2.405 2.32-.648 1.332 2.006z" style="fill:#000;fill-opacity:1;stroke-width:6;stroke-linecap:square;stroke-linejoin:round" transform="rotate(38.951 8.225 -4.95)scale(.63342)"/>
<path d="M34.79 11.804 31.165 9.71l3.627-2.094Z" style="fill:#000;fill-opacity:1;stroke-width:6;stroke-linecap:square;stroke-linejoin:round" transform="rotate(38.951 16.064 -7.581)scale(.80453)"/>
<path d="M34.79 11.804 31.165 9.71l3.627-2.094Z" style="fill:#000;fill-opacity:1;stroke-width:6;stroke-linecap:square;stroke-linejoin:round" transform="rotate(-33.724 21.526 30.482)scale(.76175)"/>
<path d="M7.088 14.395v3.071h1.198v-3.071zM7.088 18.514v1.723h1.198v-1.723zM17.228 14.395v3.071h1.198v-3.071zM17.228 18.514v1.723h1.198v-1.723z" style="fill:#000;stroke-width:1.19817;stroke-linecap:square;stroke-linejoin:round" transform="translate(.365 -.337)"/>
<path d="m34.133 11.683-2.257-.84.1-2.405 2.32-.648 1.332 2.006z" style="fill:#000;fill-opacity:1;stroke-width:6;stroke-linecap:square;stroke-linejoin:round" transform="rotate(218.951 18.726 11.626)scale(.63342)"/>
<path d="M34.79 11.804 31.165 9.71l3.627-2.094Z" style="fill:#000;fill-opacity:1;stroke-width:6;stroke-linecap:square;stroke-linejoin:round" transform="rotate(218.951 22.916 15.042)scale(.80453)"/>
<path d="M34.79 11.804 31.165 9.71l3.627-2.094Z" style="fill:#000;fill-opacity:1;stroke-width:6;stroke-linecap:square;stroke-linejoin:round" transform="rotate(146.276 17.093 9.794)scale(.76175)"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="26" height="33" version="1.1" viewBox="0 0 26 33" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="linearGradient1" x1="13" x2="13" y1="1" y2="30" gradientUnits="userSpaceOnUse">
<stop stop-color="#e8514e" offset="0"/>
<stop stop-color="#cc3633" offset="1"/>
</linearGradient>
<filter id="filter1" x="-.0882" y="-.441" width="1.1764" height="1.882" color-interpolation-filters="sRGB">
<feGaussianBlur stdDeviation="0.55125"/>
</filter>
</defs>
<ellipse cx="13" cy="30.177" rx="7.5" ry="1.5" filter="url(#filter1)" opacity=".1" stroke-linecap="round" stroke-linejoin="round"/>
<path d="m13 1c-6.3513 0-11.5 5.1487-11.5 11.5 2.4e-4 4.6124 2.7473 8.7238 6.8871 10.534 0.76685 0.33537 1.7261 1.1233 2.097 1.8742l2.5159 5.0935 2.5159-5.0935c0.37091-0.75091 1.3301-1.5388 2.0969-1.8742 4.1398-1.8104 6.8869-5.9219 6.8871-10.534 0-6.3513-5.1487-11.5-11.5-11.5z" fill="url(#linearGradient1)" stroke="#fff" stroke-linejoin="round" stroke-width="2"/>
<path d="m11.91 13.481-0.31705-4.7458q-0.08917-1.3871-0.08917-1.9915 0-0.82234 0.42603-1.2781 0.43594-0.46566 1.1394-0.46566 0.85206 0 1.1394 0.59446 0.28732 0.58456 0.28732 1.6942 0 0.65391-0.06935 1.3276l-0.42603 4.8845q-0.06935 0.87188-0.29723 1.3375-0.22788 0.46566-0.75299 0.46566-0.53502 0-0.74308-0.44585-0.20806-0.45576-0.29724-1.3772zm1.0998 6.5193q-0.60437 0-1.0601-0.3864-0.44585-0.39631-0.44585-1.0998 0-0.61428 0.42603-1.0403 0.43594-0.43594 1.0601-0.43594t1.0601 0.43594q0.44585 0.42603 0.44585 1.0403 0 0.69354-0.44585 1.0898-0.44585 0.39631-1.0403 0.39631z" fill="#fff" aria-label="!" data-font-family="Arial Rounded MT Bold"/>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1,15 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" width="26" height="33" viewBox="0 0 26 33">
<svg width="26" height="33" version="1.1" viewBox="0 0 26 33" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
<defs> <defs>
<linearGradient id="linearGradient1" x1="13" x2="13" y1="1" y2="30" gradientUnits="userSpaceOnUse"> <linearGradient id="a" x1="13" x2="13" y1="1" y2="30" gradientUnits="userSpaceOnUse">
<stop stop-color="#e8514e" offset="0"/> <stop offset="0" stop-color="#e8514e"/>
<stop stop-color="#cc3633" offset="1"/> <stop offset="1" stop-color="#cc3633"/>
</linearGradient> </linearGradient>
<filter id="filter1" x="-.0882" y="-.441" width="1.1764" height="1.882" color-interpolation-filters="sRGB"> <linearGradient xlink:href="#a" id="d" x1="13" x2="13" y1="1" y2="30" gradientTransform="translate(.122 .703)" gradientUnits="userSpaceOnUse"/>
<feGaussianBlur stdDeviation="0.55125"/> <filter id="b" width="1.176" height="1.882" x="-.088" y="-.441" color-interpolation-filters="sRGB">
<feGaussianBlur stdDeviation=".551"/>
</filter> </filter>
</defs> <filter id="c" width="1.176" height="1.882" x="-.088" y="-.441" color-interpolation-filters="sRGB">
<ellipse cx="13" cy="30.177" rx="7.5" ry="1.5" filter="url(#filter1)" opacity=".1" stroke-linecap="round" stroke-linejoin="round"/> <feGaussianBlur stdDeviation=".551"/>
<path d="m13 1c-6.3513 0-11.5 5.1487-11.5 11.5 2.4e-4 4.6124 2.7473 8.7238 6.8871 10.534 0.76685 0.33537 1.7261 1.1233 2.097 1.8742l2.5159 5.0935 2.5159-5.0935c0.37091-0.75091 1.3301-1.5388 2.0969-1.8742 4.1398-1.8104 6.8869-5.9219 6.8871-10.534 0-6.3513-5.1487-11.5-11.5-11.5z" fill="url(#linearGradient1)" stroke="#fff" stroke-linejoin="round" stroke-width="2"/> </filter>
<path d="m11.91 13.481-0.31705-4.7458q-0.08917-1.3871-0.08917-1.9915 0-0.82234 0.42603-1.2781 0.43594-0.46566 1.1394-0.46566 0.85206 0 1.1394 0.59446 0.28732 0.58456 0.28732 1.6942 0 0.65391-0.06935 1.3276l-0.42603 4.8845q-0.06935 0.87188-0.29723 1.3375-0.22788 0.46566-0.75299 0.46566-0.53502 0-0.74308-0.44585-0.20806-0.45576-0.29724-1.3772zm1.0998 6.5193q-0.60437 0-1.0601-0.3864-0.44585-0.39631-0.44585-1.0998 0-0.61428 0.42603-1.0403 0.43594-0.43594 1.0601-0.43594t1.0601 0.43594q0.44585 0.42603 0.44585 1.0403 0 0.69354-0.44585 1.0898-0.44585 0.39631-1.0403 0.39631z" fill="#fff" aria-label="!" data-font-family="Arial Rounded MT Bold"/> </defs>
<ellipse cx="13.122" cy="30.88" filter="url(#b)" opacity=".1" rx="7.5" ry="1.5" style="filter:url(#c)"/>
<path fill="url(#a)" stroke="#fff" stroke-linejoin="round" stroke-width="2" d="M13.122 1.703c-6.352 0-11.5 5.149-11.5 11.5a11.5 11.5 0 0 0 6.887 10.534c.766.335 1.726 1.123 2.097 1.874l2.516 5.094 2.515-5.094c.371-.75 1.33-1.539 2.097-1.874a11.5 11.5 0 0 0 6.887-10.534c0-6.351-5.148-11.5-11.5-11.5z" style="fill:url(#d)"/>
<path d="M17.228 10.192v3.071h1.198v-3.071ZM17.228 7.424v1.721h1.198V7.423ZM7.088 10.192v3.071h1.198v-3.071ZM7.088 7.424v1.721h1.198V7.423Z" style="fill:#fff;stroke-width:1.19817;stroke-linecap:square;stroke-linejoin:round" transform="translate(.365 -.337)"/>
<path d="m34.133 11.683-2.257-.84.1-2.405 2.32-.648 1.332 2.006z" style="fill:#fff;fill-opacity:1;stroke-width:6;stroke-linecap:square;stroke-linejoin:round" transform="rotate(38.951 8.225 -4.95)scale(.63342)"/>
<path d="M34.79 11.804 31.165 9.71l3.627-2.094Z" style="fill:#fff;fill-opacity:1;stroke-width:6;stroke-linecap:square;stroke-linejoin:round" transform="rotate(38.951 16.064 -7.581)scale(.80453)"/>
<path d="M34.79 11.804 31.165 9.71l3.627-2.094Z" style="fill:#fff;fill-opacity:1;stroke-width:6;stroke-linecap:square;stroke-linejoin:round" transform="rotate(-33.724 21.526 30.482)scale(.76175)"/>
<path d="M7.088 14.395v3.071h1.198v-3.071zM7.088 18.514v1.723h1.198v-1.723zM17.228 14.395v3.071h1.198v-3.071zM17.228 18.514v1.723h1.198v-1.723z" style="fill:#fff;stroke-width:1.19817;stroke-linecap:square;stroke-linejoin:round" transform="translate(.365 -.337)"/>
<path d="m34.133 11.683-2.257-.84.1-2.405 2.32-.648 1.332 2.006z" style="fill:#fff;fill-opacity:1;stroke-width:6;stroke-linecap:square;stroke-linejoin:round" transform="rotate(218.951 18.726 11.626)scale(.63342)"/>
<path d="M34.79 11.804 31.165 9.71l3.627-2.094Z" style="fill:#fff;fill-opacity:1;stroke-width:6;stroke-linecap:square;stroke-linejoin:round" transform="rotate(218.951 22.916 15.042)scale(.80453)"/>
<path d="M34.79 11.804 31.165 9.71l3.627-2.094Z" style="fill:#fff;fill-opacity:1;stroke-width:6;stroke-linecap:square;stroke-linejoin:round" transform="rotate(146.276 17.093 9.794)scale(.76175)"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -1 +1 @@
© 2025 CoMaps Contributors © 2026 CoMaps Contributors

View File

@@ -22,13 +22,26 @@ vim /etc/nginx/nginx.conf
access_log /var/log/nginx/access.log comaps; access_log /var/log/nginx/access.log comaps;
``` ```
if using Apache, try this:
```
LogFormat "0.0.0.0 %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" comaps
CustomLog ${APACHE_LOG_DIR}/access.log comaps
```
### set up monitoring: ### set up monitoring:
apt install goaccess apt install goaccess
edit /etc/goaccess/goaccess.conf and uncomment time-format %H:%M:%S, date-format %Y-%m-%d, log-format COMBINED edit /etc/goaccess/goaccess.conf and uncomment:
- time-format %H:%M:%S
- date-format %d/%b/%Y
- log-format COMBINED
vim /etc/crontab vim /etc/crontab
`*/5 * * * * root /usr/bin/goaccess /var/log/nginx/access.log -o /var/www/html/monitor.html` `*/5 * * * * root /usr/bin/goaccess /var/log/nginx/access.log -o /var/www/html/monitor.html`
or Apache: `*/5 * * * * root /usr/bin/goaccess /var/log/apache2/access.log -o /var/www/html/monitor.html`
### set up basic http pages/responses: ### set up basic http pages/responses:
cd /var/www/html/ cd /var/www/html/
mkdir maps mkdir maps