diff --git a/.github/workflows/containers.yml b/.github/workflows/containers.yml index 3d8935d6..244b4d04 100644 --- a/.github/workflows/containers.yml +++ b/.github/workflows/containers.yml @@ -96,8 +96,9 @@ jobs: tags: | ${{ secrets.DOCKER_HUB_USERNAME }}/changedetection.io:dev,ghcr.io/${{ github.repository }}:dev platforms: linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7,linux/arm/v8 - cache-from: type=local,src=/tmp/.buildx-cache - cache-to: type=local,dest=/tmp/.buildx-cache + cache-from: type=gha + cache-to: type=gha,mode=max + # Looks like this was disabled # provenance: false @@ -116,18 +117,11 @@ jobs: ${{ secrets.DOCKER_HUB_USERNAME }}/changedetection.io:latest ghcr.io/dgtlmoon/changedetection.io:latest platforms: linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7,linux/arm/v8 - cache-from: type=local,src=/tmp/.buildx-cache - cache-to: type=local,dest=/tmp/.buildx-cache + cache-from: type=gha + cache-to: type=gha,mode=max # Looks like this was disabled # provenance: false - name: Image digest run: echo step SHA ${{ steps.vars.outputs.sha_short }} tag ${{steps.vars.outputs.tag}} branch ${{steps.vars.outputs.branch}} digest ${{ steps.docker_build.outputs.digest }} - - name: Cache Docker layers - uses: actions/cache@v3 - with: - path: /tmp/.buildx-cache - key: ${{ runner.os }}-buildx-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-buildx- diff --git a/Dockerfile b/Dockerfile index d0f4ea75..e726d26e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,17 +20,12 @@ WORKDIR /install COPY requirements.txt /requirements.txt -# Instructing pip to fetch wheels from piwheels.org" on ARMv6 and ARMv7 machines -RUN if [ "$(dpkg --print-architecture)" = "armhf" ] || [ "$(dpkg --print-architecture)" = "armel" ]; then \ - printf "[global]\nextra-index-url=https://www.piwheels.org/simple\n" > /etc/pip.conf; \ - fi; - RUN pip install --target=/dependencies -r /requirements.txt # Playwright is an alternative to Selenium # Excluded this package from requirements.txt to prevent arm/v6 and arm/v7 builds from failing # https://github.com/dgtlmoon/changedetection.io/pull/1067 also musl/alpine (not supported) -RUN pip install --target=/dependencies playwright~=1.27.1 \ +RUN pip install --target=/dependencies playwright~=1.39 \ || echo "WARN: Failed to install Playwright. The application can still run, but the Playwright option will be disabled." # Final image stage diff --git a/MANIFEST.in b/MANIFEST.in index 41ed620d..f7393309 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -16,3 +16,4 @@ global-exclude venv global-exclude test-datastore global-exclude changedetection.io*dist-info +global-exclude changedetectionio/tests/proxy_socks5/test-datastore diff --git a/README.md b/README.md index 76595426..67de6c11 100644 --- a/README.md +++ b/README.md @@ -232,6 +232,13 @@ See the wiki https://github.com/dgtlmoon/changedetection.io/wiki/Proxy-configura Raspberry Pi and linux/arm/v6 linux/arm/v7 arm64 devices are supported! See the wiki for [details](https://github.com/dgtlmoon/changedetection.io/wiki/Fetching-pages-with-WebDriver) +## Import support + +Easily [import your list of websites to watch for changes in Excel .xslx file format](https://changedetection.io/tutorial/how-import-your-website-change-detection-lists-excel), or paste in lists of website URLs as plaintext. + +Excel import is recommended - that way you can better organise tags/groups of websites and other features. + + ## API Support Supports managing the website watch list [via our API](https://changedetection.io/docs/api_v1/index.html) diff --git a/changedetectionio/__init__.py b/changedetectionio/__init__.py index eeddb8cc..fd2e6256 100644 --- a/changedetectionio/__init__.py +++ b/changedetectionio/__init__.py @@ -38,7 +38,7 @@ from flask_paginate import Pagination, get_page_parameter from changedetectionio import html_tools from changedetectionio.api import api_v1 -__version__ = '0.45.5' +__version__ = '0.45.7.3' from changedetectionio.store import BASE_URL_NOT_SET_TEXT @@ -105,6 +105,10 @@ def get_darkmode_state(): css_dark_mode = request.cookies.get('css_dark_mode', 'false') return 'true' if css_dark_mode and strtobool(css_dark_mode) else 'false' +@app.template_global() +def get_css_version(): + return __version__ + # We use the whole watch object from the store/JSON so we can see if there's some related status in terms of a thread # running or something similar. @app.template_filter('format_last_checked_time') @@ -1210,8 +1214,7 @@ def changedetection_app(config=None, datastore_o=None): # These files should be in our subdirectory try: # set nocache, set content-type - watch_dir = datastore_o.datastore_path + "/" + filename - response = make_response(send_from_directory(filename="elements.json", directory=watch_dir, path=watch_dir + "/elements.json")) + response = make_response(send_from_directory(os.path.join(datastore_o.datastore_path, filename), "elements.json")) response.headers['Content-type'] = 'application/json' response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate' response.headers['Pragma'] = 'no-cache' diff --git a/changedetectionio/blueprint/check_proxies/__init__.py b/changedetectionio/blueprint/check_proxies/__init__.py index 06abdfee..ea68376a 100644 --- a/changedetectionio/blueprint/check_proxies/__init__.py +++ b/changedetectionio/blueprint/check_proxies/__init__.py @@ -41,7 +41,7 @@ def construct_blueprint(datastore: ChangeDetectionStore): now = time.time() try: update_handler = text_json_diff.perform_site_check(datastore=datastore, watch_uuid=uuid) - changed_detected, update_obj, contents = update_handler.call_browser() + update_handler.call_browser() # title, size is len contents not len xfer except content_fetcher.Non200ErrorCodeReceived as e: if e.status_code == 404: diff --git a/changedetectionio/processors/__init__.py b/changedetectionio/processors/__init__.py index c719d7a2..10c9138c 100644 --- a/changedetectionio/processors/__init__.py +++ b/changedetectionio/processors/__init__.py @@ -7,12 +7,13 @@ from copy import deepcopy from distutils.util import strtobool class difference_detection_processor(): + + browser_steps = None datastore = None fetcher = None screenshot = None - xpath_data = None - browser_steps = None watch = None + xpath_data = None def __init__(self, *args, datastore, watch_uuid, **kwargs): super().__init__(*args, **kwargs) diff --git a/changedetectionio/static/js/toggle-theme.js b/changedetectionio/static/js/toggle-theme.js index 885b8907..774729d0 100644 --- a/changedetectionio/static/js/toggle-theme.js +++ b/changedetectionio/static/js/toggle-theme.js @@ -3,45 +3,50 @@ * Toggles theme between light and dark mode. */ $(document).ready(function () { - const button = document.getElementById("toggle-light-mode"); + const button = document.getElementById("toggle-light-mode"); - button.onclick = () => { - const htmlElement = document.getElementsByTagName("html"); - const isDarkMode = htmlElement[0].dataset.darkmode === "true"; - htmlElement[0].dataset.darkmode = !isDarkMode; - setCookieValue(!isDarkMode); - }; + button.onclick = () => { + const htmlElement = document.getElementsByTagName("html"); + const isDarkMode = htmlElement[0].dataset.darkmode === "true"; + htmlElement[0].dataset.darkmode = !isDarkMode; + setCookieValue(!isDarkMode); + }; - const setCookieValue = (value) => { - document.cookie = `css_dark_mode=${value};max-age=31536000;path=/` - } + const setCookieValue = (value) => { + document.cookie = `css_dark_mode=${value};max-age=31536000;path=/` + } - // Search input box behaviour + // Search input box behaviour const toggle_search = document.getElementById("toggle-search"); - const search_q = document.getElementById("search-q"); - window.addEventListener('keydown', function (e) { - - if (e.altKey == true && e.keyCode == 83) - search_q.classList.toggle('expanded'); - search_q.focus(); - }); + const search_q = document.getElementById("search-q"); + if(search_q) { + window.addEventListener('keydown', function (e) { + if (e.altKey == true && e.keyCode == 83) { + search_q.classList.toggle('expanded'); + search_q.focus(); + } + }); - - search_q.onkeydown = (e) => { - var key = e.keyCode || e.which; - if (key === 13) { - document.searchForm.submit(); - } - }; - toggle_search.onclick = () => { - // Could be that they want to search something once text is in there - if (search_q.value.length) { - document.searchForm.submit(); - } else { - // If not.. - search_q.classList.toggle('expanded'); - search_q.focus(); + search_q.onkeydown = (e) => { + var key = e.keyCode || e.which; + if (key === 13) { + document.searchForm.submit(); + } + }; + toggle_search.onclick = () => { + // Could be that they want to search something once text is in there + if (search_q.value.length) { + document.searchForm.submit(); + } else { + // If not.. + search_q.classList.toggle('expanded'); + search_q.focus(); + } + }; } - }; + $('#heart-us').click(function () { + $("#overlay").toggleClass('visible'); + heartpath.style.fill = document.getElementById("overlay").classList.contains("visible") ? '#ff0000' : 'var(--color-background)'; + }); }); diff --git a/changedetectionio/static/styles/scss/parts/_darkmode.scss b/changedetectionio/static/styles/scss/parts/_darkmode.scss index a9719d3c..6a80ecf6 100644 --- a/changedetectionio/static/styles/scss/parts/_darkmode.scss +++ b/changedetectionio/static/styles/scss/parts/_darkmode.scss @@ -1,6 +1,6 @@ #toggle-light-mode { - width: 3rem; +/* width: 3rem;*/ /* default */ .icon-dark { display: none; diff --git a/changedetectionio/static/styles/scss/parts/_love.scss b/changedetectionio/static/styles/scss/parts/_love.scss new file mode 100644 index 00000000..d2aad23d --- /dev/null +++ b/changedetectionio/static/styles/scss/parts/_love.scss @@ -0,0 +1,38 @@ +#overlay { + + opacity: 0.95; + position: fixed; + + width: 350px; + max-width: 100%; + height: 100%; + top: 0; + right: -350px; + background-color: var(--color-table-stripe); + z-index: 2; + + transform: translateX(0); + transition: transform .5s ease; + + + &.visible { + transform: translateX(-100%); + + } + + .content { + font-size: 0.875rem; + padding: 1rem; + margin-top: 5rem; + max-width: 400px; + color: var(--color-watch-table-row-text); + } +} + +#heartpath { + &:hover { + fill: #ff0000 !important; + transition: all ease 0.3s !important; + } + transition: all ease 0.3s !important; +} diff --git a/changedetectionio/static/styles/scss/parts/_menu.scss b/changedetectionio/static/styles/scss/parts/_menu.scss new file mode 100644 index 00000000..22322eb8 --- /dev/null +++ b/changedetectionio/static/styles/scss/parts/_menu.scss @@ -0,0 +1,25 @@ +.pure-menu-link { + padding: 0.5rem 1em; + line-height: 1.2rem; +} + +.pure-menu-item { + svg { + height: 1.2rem; + } + * { + vertical-align: middle; + } + .github-link { + height: 1.8rem; + display: block; + svg { + height: 100%; + } + } + .bi-heart { + &:hover { + cursor: pointer; + } + } +} diff --git a/changedetectionio/static/styles/scss/styles.scss b/changedetectionio/static/styles/scss/styles.scss index 77cee346..ed98a1c6 100644 --- a/changedetectionio/static/styles/scss/styles.scss +++ b/changedetectionio/static/styles/scss/styles.scss @@ -10,10 +10,13 @@ @import "parts/_spinners"; @import "parts/_variables"; @import "parts/_darkmode"; +@import "parts/_menu"; +@import "parts/_love"; body { color: var(--color-text); background: var(--color-background-page); + font-family: Helvetica Neue, Helvetica, Lucida Grande, Arial, Ubuntu, Cantarell, Fira Sans, sans-serif; } .visually-hidden { @@ -56,11 +59,6 @@ a.github-link { } } - -#toggle-search { - width: 2rem; -} - #search-q { opacity: 0; -webkit-transition: all .9s ease; @@ -1083,3 +1081,4 @@ ul { border-radius: 3px; white-space: nowrap; } + diff --git a/changedetectionio/static/styles/styles.css b/changedetectionio/static/styles/styles.css index 3431d250..c1865879 100644 --- a/changedetectionio/static/styles/styles.css +++ b/changedetectionio/static/styles/styles.css @@ -352,7 +352,7 @@ html[data-darkmode="true"] { color: var(--color-watch-table-error); } #toggle-light-mode { - width: 3rem; + /* width: 3rem;*/ /* default */ } #toggle-light-mode .icon-dark { display: none; } @@ -363,9 +363,56 @@ html[data-darkmode="true"] #toggle-light-mode .icon-light { html[data-darkmode="true"] #toggle-light-mode .icon-dark { display: block; } +.pure-menu-link { + padding: 0.5rem 1em; + line-height: 1.2rem; } + +.pure-menu-item svg { + height: 1.2rem; } + +.pure-menu-item * { + vertical-align: middle; } + +.pure-menu-item .github-link { + height: 1.8rem; + display: block; } + .pure-menu-item .github-link svg { + height: 100%; } + +.pure-menu-item .bi-heart:hover { + cursor: pointer; } + +#overlay { + opacity: 0.95; + position: fixed; + width: 350px; + max-width: 100%; + height: 100%; + top: 0; + right: -350px; + background-color: var(--color-table-stripe); + z-index: 2; + transform: translateX(0); + transition: transform .5s ease; } + #overlay.visible { + transform: translateX(-100%); } + #overlay .content { + font-size: 0.875rem; + padding: 1rem; + margin-top: 5rem; + max-width: 400px; + color: var(--color-watch-table-row-text); } + +#heartpath { + transition: all ease 0.3s !important; } + #heartpath:hover { + fill: #ff0000 !important; + transition: all ease 0.3s !important; } + body { color: var(--color-text); - background: var(--color-background-page); } + background: var(--color-background-page); + font-family: Helvetica Neue, Helvetica, Lucida Grande, Arial, Ubuntu, Cantarell, Fira Sans, sans-serif; } .visually-hidden { clip: rect(0 0 0 0); @@ -397,9 +444,6 @@ a.github-link { a.github-link:hover { color: var(--color-icon-github-hover); } -#toggle-search { - width: 2rem; } - #search-q { opacity: 0; -webkit-transition: all .9s ease; diff --git a/changedetectionio/templates/base.html b/changedetectionio/templates/base.html index e8ef295a..92cf242d 100644 --- a/changedetectionio/templates/base.html +++ b/changedetectionio/templates/base.html @@ -8,10 +8,10 @@ Change Detection{{extra_title}} - + {% if extra_stylesheets %} {% for m in extra_stylesheets %} - + {% endfor %} {% endif %} @@ -108,6 +108,20 @@ +
  • + + + + +
  • {% include "svgs/github.svg" %} @@ -131,7 +145,44 @@
    {{ right_sticky }}
    {% endif %}
    -
    +
    +
    + changedetection.io needs your support!
    +

    + You can help us by supporting changedetection.io on these platforms; +

    +

    +

    +

    +

    + The more popular changedetection.io is, the more time we can dedicate to adding amazing features! +

    +

    + Many thanks :)
    +

    +

    + changedetection.io team +

    +
    +
    +
    {% block header %}{% endblock %}
    diff --git a/changedetectionio/templates/svgs/github.svg b/changedetectionio/templates/svgs/github.svg index 31eef6df..6e7f97a2 100644 --- a/changedetectionio/templates/svgs/github.svg +++ b/changedetectionio/templates/svgs/github.svg @@ -1,3 +1,6 @@ -