Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions changedetectionio/blueprint/watchlist/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import flask_login
import os
import time
import timeago

from flask import Blueprint, request, make_response, render_template, redirect, url_for, flash, session
from flask_login import current_user
Expand All @@ -10,7 +8,6 @@
from changedetectionio import forms
from changedetectionio.store import ChangeDetectionStore
from changedetectionio.auth_decorator import login_optionally_required
from changedetectionio.strtobool import strtobool

def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMetaData):
watchlist_blueprint = Blueprint('watchlist', __name__, template_folder="templates")
Expand Down Expand Up @@ -77,7 +74,6 @@ def index():
sorted_tags = sorted(datastore.data['settings']['application'].get('tags').items(), key=lambda x: x[1]['title'])
output = render_template(
"watch-overview.html",
# Don't link to hosting when we're on the hosting environment
active_tag=active_tag,
active_tag_uuid=active_tag_uuid,
app_rss_token=datastore.data['settings']['application'].get('rss_access_token'),
Expand All @@ -88,9 +84,10 @@ def index():
has_proxies=datastore.proxy_list,
has_unviewed=datastore.has_unviewed,
hosted_sticky=os.getenv("SALTED_PASS", False) == False,
now_time_server=time.time(),
pagination=pagination,
queued_uuids=[q_uuid.item['uuid'] for q_uuid in update_q.queue],
search_q=request.args.get('q','').strip(),
search_q=request.args.get('q', '').strip(),
sort_attribute=request.args.get('sort') if request.args.get('sort') else request.cookies.get('sort'),
sort_order=request.args.get('order') if request.args.get('order') else request.cookies.get('order'),
system_default_fetcher=datastore.data['settings']['application'].get('fetch_backend'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,16 @@
{% from '_helpers.html' import render_simple_field, render_field, render_nolabel_field, sort_by_title %}
<script src="{{url_for('static_content', group='js', filename='jquery-3.6.0.min.js')}}"></script>
<script src="{{url_for('static_content', group='js', filename='watch-overview.js')}}" defer></script>

<script>let nowtimeserver={{ now_time_server }};</script>

<style>
.checking-now .last-checked {
background-image: linear-gradient(to bottom, transparent 0%, rgba(0,0,0,0.05) 40%, rgba(0,0,0,0.1) 100%);
background-size: 0 100%;
background-repeat: no-repeat;
transition: background-size 0.9s ease
}
</style>
<div class="box">

<form class="pure-form" action="{{ url_for('ui.ui_views.form_quick_watch_add', tag=active_tag_uuid) }}" method="POST" id="new-watch-form">
Expand Down Expand Up @@ -91,16 +100,18 @@
{% endif %}
{% for watch in (watches|sort(attribute=sort_attribute, reverse=sort_order == 'asc'))|pagination_slice(skip=pagination.skip) %}

{% set is_unviewed = watch.newest_history_key| int > watch.last_viewed and watch.history_n>=2 %}

{% set is_unviewed = watch.newest_history_key| int > watch.last_viewed and watch.history_n>=2 %}
{% set checking_now = is_checking_now(watch) %}
<tr id="{{ watch.uuid }}"
class="{{ loop.cycle('pure-table-odd', 'pure-table-even') }} processor-{{ watch['processor'] }}
{% if watch.last_error is defined and watch.last_error != False %}error{% endif %}
{% if watch.last_notification_error is defined and watch.last_notification_error != False %}error{% endif %}
{% if watch.paused is defined and watch.paused != False %}paused{% endif %}
{% if is_unviewed %}unviewed{% endif %}
{% if watch.has_restock_info %} has-restock-info {% if watch['restock']['in_stock'] %}in-stock{% else %}not-in-stock{% endif %} {% else %}no-restock-info{% endif %}
{% if watch.uuid in queued_uuids %}queued{% endif %}">
{% if watch.uuid in queued_uuids %}queued{% endif %}
{% if checking_now %}checking-now{% endif %}
">
<td class="inline checkbox-uuid" ><input name="uuids" type="checkbox" value="{{ watch.uuid}} " > <span>{{ loop.index+pagination.skip }}</span></td>
<td class="inline watch-controls">
{% if not watch.paused %}
Expand Down Expand Up @@ -178,7 +189,14 @@
{% endif %}
</td>
{% endif %}
<td class="last-checked" data-timestamp="{{ watch.last_checked }}">{{watch|format_last_checked_time|safe}}</td>
{#last_checked becomes fetch-start-time#}
<td class="last-checked" data-timestamp="{{ watch.last_checked }}" {% if checking_now %} data-fetchduration={{ watch.fetch_time }} data-eta_complete="{{ watch.last_checked+watch.fetch_time }}" {% endif %} >
{% if checking_now %}
<span class="spinner"></span><span> Checking now</span>
{% else %}
{{watch|format_last_checked_time|safe}}</td>
{% endif %}

<td class="last-changed" data-timestamp="{{ watch.last_changed }}">{% if watch.history_n >=2 and watch.last_changed >0 %}
{{watch.last_changed|format_timestamp_timeago}}
{% else %}
Expand Down
12 changes: 8 additions & 4 deletions changedetectionio/flask_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,18 @@ def _jinja2_filter_format_number_locale(value: float) -> str:

return formatted_value

@app.template_global('is_checking_now')
def _watch_is_checking_now(watch_obj, format="%Y-%m-%d %H:%M:%S"):
# Worker thread tells us which UUID it is currently processing.
for t in running_update_threads:
if t.current_uuid == watch_obj['uuid']:
return True


# 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')
def _jinja2_filter_datetime(watch_obj, format="%Y-%m-%d %H:%M:%S"):
# Worker thread tells us which UUID it is currently processing.
for t in running_update_threads:
if t.current_uuid == watch_obj['uuid']:
return '<span class="spinner"></span><span> Checking now</span>'

if watch_obj['last_checked'] == 0:
return 'Not yet'
Expand Down
27 changes: 27 additions & 0 deletions changedetectionio/static/js/watch-overview.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ $(function () {
$('input[type=checkbox]').not(this).prop('checked', this.checked);
});

const time_check_step_size_seconds=1;

// checkboxes - show/hide buttons
$("input[type=checkbox]").click(function (e) {
if ($('input[type=checkbox]:checked').length) {
Expand All @@ -57,5 +59,30 @@ $(function () {
}
});

setInterval(function () {
// Background ETA completion for 'checking now'
$(".watch-table .checking-now .last-checked").each(function () {
const eta_complete = parseFloat($(this).data('eta_complete'));
const fetch_duration = parseInt($(this).data('fetchduration'));

if (eta_complete + 2 > nowtimeserver && fetch_duration > 3) {
const remaining_seconds = Math.abs(eta_complete) - nowtimeserver - 1;

let r = (1.0 - (remaining_seconds / fetch_duration)) * 100;
if (r < 10) {
r = 10;
}
if (r >= 90) {
r = 100;
}
$(this).css('background-size', `${r}% 100%`);
//$(this).text(`${r}% remain ${remaining_seconds}`);
} else {
$(this).css('background-size', `100% 100%`);
}
});

nowtimeserver = nowtimeserver + time_check_step_size_seconds;
}, time_check_step_size_seconds * 1000);
});

10 changes: 4 additions & 6 deletions changedetectionio/update_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,17 +253,20 @@ def run(self):
pass

else:
fetch_start_time = time.time()

uuid = queued_item_data.item.get('uuid')
fetch_start_time = round(time.time()) # Also used for a unique history key for now
self.current_uuid = uuid
if uuid in list(self.datastore.data['watching'].keys()) and self.datastore.data['watching'][uuid].get('url'):
changed_detected = False
contents = b''
process_changedetection_results = True
update_obj = {}


# Clear last errors (move to preflight func?)
self.datastore.data['watching'][uuid]['browser_steps_last_error_step'] = None
self.datastore.data['watching'][uuid]['last_checked'] = fetch_start_time

watch = self.datastore.data['watching'].get(uuid)

Expand All @@ -287,10 +290,6 @@ def run(self):

update_handler.call_browser()

# In reality, the actual time of when the change was detected could be a few seconds after this
# For example it should include when the page stopped rendering if using a playwright/chrome type fetch
fetch_start_time = time.time()

changed_detected, update_obj, contents = update_handler.run_changedetection(watch=watch)

# Re #342
Expand Down Expand Up @@ -587,7 +586,6 @@ def run(self):
pass

self.datastore.update_watch(uuid=uuid, update_obj={'fetch_time': round(time.time() - fetch_start_time, 3),
'last_checked': int(fetch_start_time),
'check_count': count
})

Expand Down