Browse Source

fixed some ui stuff and added more ui stuff

sleepytaco 3 years ago
parent
commit
2c9bf170a1

+ 19 - 0
apps/main/migrations/0044_tag_last_views_reset.py

@@ -0,0 +1,19 @@
+# Generated by Django 3.2.3 on 2021-07-31 03:39
+
+import datetime
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('main', '0043_auto_20210723_2326'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='tag',
+            name='last_views_reset',
+            field=models.DateTimeField(default=datetime.datetime.now),
+        ),
+    ]

+ 18 - 0
apps/main/migrations/0045_tag_times_viewed_per_week.py

@@ -0,0 +1,18 @@
+# Generated by Django 3.2.3 on 2021-07-31 03:50
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('main', '0044_tag_last_views_reset'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='tag',
+            name='times_viewed_per_week',
+            field=models.IntegerField(default=0),
+        ),
+    ]

+ 17 - 5
apps/main/models.py

@@ -1,3 +1,5 @@
+import datetime
+
 import requests
 from django.contrib.auth.models import User
 from allauth.socialaccount.models import SocialAccount, SocialApp, SocialToken
@@ -542,14 +544,15 @@ class PlaylistManager(models.Manager):
                     except AttributeError:
                         break
 
-            playlist.last_full_scan_at = datetime.datetime.now(pytz.utc)
+            # playlist.last_full_scan_at = datetime.datetime.now(pytz.utc)
 
             playlist.save()
 
             deleted_videos = len(current_playlist_item_ids)  # left out video ids
 
             return [1, deleted_videos, unavailable_videos, added_videos]
-
+        else:
+            print("YOU CAN DO A FULL SCAN AGAIN IN", str(datetime.datetime.now(pytz.utc) - (playlist.last_full_scan_at + datetime.timedelta(minutes=1))))
         """
         print("DOING A SMOL SCAN")
 
@@ -900,6 +903,7 @@ class PlaylistManager(models.Manager):
         playlist.has_playlist_changed = False
         playlist.video_count = updated_playlist_video_count
         playlist.has_new_updates = True
+        playlist.last_full_scan_at = datetime.datetime.now(pytz.utc)
         playlist.save()
 
         deleted_playlist_item_ids = current_playlist_item_ids  # left out playlist_item_ids
@@ -974,9 +978,13 @@ class PlaylistManager(models.Manager):
 
                 if not playlist.playlist_items.filter(video__video_id=video.video_id).exists():
                     playlist.videos.remove(video)
-                    if video.playlists.all().count() == 0: # also delete the video if it is not found in other playlists
+                    if video.playlists.all().count() == 0:  # also delete the video if it is not found in other playlists
                         video.delete()
 
+                if playlist_id == "LL":
+                    video.liked = False
+                    video.save(update_fields=['liked'])
+
                 new_playlist_video_count -= 1
                 new_playlist_duration_in_seconds -= video.duration_in_seconds
 
@@ -985,7 +993,8 @@ class PlaylistManager(models.Manager):
             playlist.thumbnail_url = ""
         playlist.playlist_duration_in_seconds = new_playlist_duration_in_seconds
         playlist.playlist_duration = getHumanizedTimeString(new_playlist_duration_in_seconds)
-        playlist.save(update_fields=['video_count', 'playlist_duration', 'playlist_duration_in_seconds', 'thumbnail_url'])
+        playlist.save(
+            update_fields=['video_count', 'playlist_duration', 'playlist_duration_in_seconds', 'thumbnail_url'])
         # time.sleep(2)
 
         playlist_items = playlist.playlist_items.select_related('video').order_by("video_position")
@@ -1167,7 +1176,7 @@ class PlaylistManager(models.Manager):
                     pl_response = pl_request.execute()
                 except googleapiclient.errors.HttpError as e:  # failed to update add video to playlis
                     print("ERROR ADDDING VIDEOS TO PLAYLIST", e.status_code, e.error_details)
-                    if e.status_code == 400: # manualSortRequired - see errors https://developers.google.com/youtube/v3/docs/playlistItems/insert
+                    if e.status_code == 400:  # manualSortRequired - see errors https://developers.google.com/youtube/v3/docs/playlistItems/insert
                         pl_request = youtube.playlistItems().insert(
                             part="snippet",
                             body={
@@ -1200,8 +1209,11 @@ class Tag(models.Model):
     created_by = models.ForeignKey(User, related_name="playlist_tags", on_delete=models.CASCADE, null=True)
 
     times_viewed = models.IntegerField(default=0)
+    times_viewed_per_week = models.IntegerField(default=0)
     # type = models.CharField(max_length=10)  # either 'playlist' or 'video'
 
+    last_views_reset = models.DateTimeField(default=datetime.datetime.now)
+
     created_at = models.DateTimeField(auto_now_add=True)
     updated_at = models.DateTimeField(auto_now=True)
 

+ 1 - 1
apps/main/templates/all_playlists.html

@@ -33,7 +33,7 @@
         {% if playlists %}
             <input   class="form-control border border-secondary" type="text"
                    name="search" placeholder="Begin to search playlists..."
-                   hx-post="{% url 'search_playlists' library_type %}"
+                   hx-post="{% url 'search_library' library_type %}"
                    hx-trigger="keyup changed delay:700ms"
                    hx-target="#search-results"
                    hx-indicator=".htmx-indicator"

+ 8 - 3
apps/main/templates/favorites.html

@@ -3,7 +3,7 @@
 {% block content %}
 
     <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
-        <h1 class="h2">Favorite Playlists
+        <h1 class="h2" id="favorite-playlists"><a href="#favorite-videos" style="color: rebeccapurple" class="mt-1 me-3"><i class="fas fa-angle-double-down"></i></a>Favorite Playlists
             <span class="badge bg-primary rounded-pill">{{ playlists.count|default:"0" }}</span>
 
         </h1>
@@ -32,7 +32,7 @@
     <br>
 
     <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
-        <h1 class="h2">Favorite Videos
+        <h1 class="h2" id="favorite-videos"><a href="#favorite-playlists" style="color: rebeccapurple" class="mt-1 me-3"><i class="fas fa-angle-double-up"></i></a>Favorite Videos
             <span class="badge bg-primary rounded-pill">{{ videos.count }}</span>
 
         </h1>
@@ -47,7 +47,7 @@
             {% endif %}
     </div>
 
-    <div>
+    <div id="favorite-videos">
         <div class="row row-cols-1 row-cols-md-3 g-4">
             {% if videos %}
                 {% include 'intercooler/video_cards.html' with videos=videos %}
@@ -56,4 +56,9 @@
             {% endif %}
         </div>
     </div>
+
+
+    <button class="scrollToTopBtn sticky-top bg-danger">
+        <i class="fa fa-angle-double-up fa-lg"></i></button>
+
 {% endblock %}

+ 21 - 39
apps/main/templates/home.html

@@ -186,49 +186,29 @@
                         </div>
                     </div>
                 </div>
-                <!-- Implement later
-                    <div class="row mt-3">
-                        <div class="col">
-
-                        </div>
-                        <div class="col-6">
-                        <div class="card">
-                            <a style="background: linear-gradient(-45deg, #e2b968, #68af5b, #8a97bc, #d69ab2); background-size: 400% 400%; animation: gradient 7s ease infinite;" href="#" class="list-group-item list-group-item-action" aria-current="true">
-                                <div class="card-body">
-                                    <div class="d-flex justify-content-center h1">
-                                        <i class="fas fa-history"></i>
-                                    </div>
-                                    <div class="d-flex justify-content-center h1">
-                                        YOUR
-                                    </div>
-                                    <div class="d-flex justify-content-center h1">
-                                        ACTIVITY
-                                    </div>
-                                </div>
-                            </a>
-                        </div>
-                        </div>
-                        <div class="col">
-
-                        </div>
-                    </div>
-                    -->
             </div>
             <div class="col">
-                <div class="card bg-transparent border border-0 text-black">
-                    <div class="card-body">
-                        <h3><span style="border-bottom: 3px #a35a5a dashed;">Most viewed playlists</span> <a href="{% url 'library' 'all' %}" class="pt-1"><i class="fas fa-binoculars"></i> </a></h3>
-                        {% if user_playlists %}
-                            <div class="row row-cols-1 row-cols-md-3 g-4 text-dark mt-0">
-                                {% include 'intercooler/playlists.html' with playlists=user_playlists|slice:"0:3" watching=False %}
-                            </div>
-                        {% else %}
-                            <br>
-                            <h5>Nothing to see here... yet.</h5>
-                        {% endif %}
-
+                <div class="d-flex justify-content-center">
+                    <h2>Popular Playlist Tags</h2>
+                </div>
 
+                <div class="d-flex justify-content-evenly h4">
+                    {% if playlist_tags %}
+                    <div class="w-100 d-flex justify-content-center flex-wrap">
+                    {% for tag in playlist_tags %}
+                        <a href="{% url 'tagged_playlists' tag.name %}" style="text-decoration: none" class="me-lg-1 mb-lg-1">
+                        <span class="badge rounded-pill bg-warning bg-gradient text-black-50">{{ tag.name }} <span class="badge bg-dark text-white">{{ tag.times_viewed_per_week }} views</span></span>
+                        </a>
+                    {% endfor %}
                     </div>
+                    {% else %}
+                        You haven't created any playlist tags yet.
+                    {% endif %}
+                </div>
+                <div class="d-flex justify-content-center">
+                    <h3>
+                        <a href="{% url 'search' %}" class="btn btn-success">Filter Playlists by Tags</a>
+                    </h3>
                 </div>
             </div>
         </div>
@@ -342,6 +322,7 @@
         <br>
 
 
+
         <footer class="footer mt-auto py-3 bg-transparent">
             <div class="container d-flex justify-content-center">
                 <span class="text-dark">Loved what I made?
@@ -351,6 +332,7 @@
             </div>
         </footer>
 
+
         <script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.3/dist/Chart.min.js"></script>
 
         <script type="application/javascript">

+ 2 - 1
apps/main/templates/intercooler/playlist_items.html

@@ -79,7 +79,8 @@
                 <div class="ms-5">
                 {% if playlist_item.video.is_unavailable_on_yt or playlist_item.video.was_deleted_on_yt %}
                 <a class="btn btn-sm  btn-primary mb-1" href="{% url 'video' playlist_item.video.video_id %}"><i class="fas fa-info"></i></a>
-                <button class="btn btn-sm btn-dark mb-1" type="button" hx-get="{% url 'mark_video_favorite' playlist_item.video.video_id %}" hx-target="#video-{{ page }}-{{ forloop.counter }}-fav">
+                <button class="btn btn-sm btn-dark mb-1" type="button" hx-get="{% url 'mark_video_favorite' playlist_item.video.video_id %}"
+                        hx-target="#video-{{ page }}-{{ forloop.counter }}-fav">
                     <div id="video-{{ page }}-{{ forloop.counter }}-fav">
                         {% if playlist_item.video.is_favorite %}
                             <i class="fas fa-heart" style="color: #fafa06"></i>

+ 2 - 0
apps/main/templates/intercooler/video_cards.html

@@ -4,9 +4,11 @@
 
         <div class="card overflow-auto" style="max-width: 540px; background-color: #1A4464;">
             <div class="row g-0">
+                {% if not video.is_unavailable_on_yt and not video.was_deleted_on_yt %}
                 <div class="col-md-4">
                     <img src="{{ video.thumbnail_url }}" class="img-fluid" style="width: 100%; height: 15vw; object-fit: cover;">
                 </div>
+                {% endif %}
                 <div class="col-md-8">
                     <div class="card-body">
                         <h5 class="card-title"><a href="{% url 'video' video.video_id %}" style="text-decoration: none; color: white">

+ 2 - 2
apps/main/templates/library.html

@@ -67,7 +67,7 @@
         <a href="{% url 'library' 'yt-mix' %}" class="text-decoration-none text-white">
         <div class="card h-100" style="background-color: #bd39a7;">
             <div class="card-body">
-                <h5 class="card-title">Your YouTube Mixes</h5>
+                <h5 class="card-title">Your YouTube Mixes <span class="badge bg-warning">BETA</span> </h5>
                 <p class="card-text">YouTube creates nice mixes that relate to songs you're currently jamming to. You can import those YT Mixes by going over to Manage. Any YouTube mixes you import will all be here.</p>
             </div>
         </div>
@@ -75,7 +75,7 @@
     </div>
 
     <div class="col">
-        <a href="#" class="text-decoration-none text-white">
+        <a href="{% url 'library' 'unavailable-videos' %}" class="text-decoration-none text-white">
         <div class="card h-100" style="background-color: #7f8675;">
             <div class="card-body">
                 <h5 class="card-title">Unavailable YouTube Videos</h5>

+ 43 - 0
apps/main/templates/unavailable_videos.html

@@ -0,0 +1,43 @@
+
+{% extends 'base.html' %}
+{% block content %}
+
+
+        <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 mb-3">
+            <h1 class="h2"><span style="border-bottom: 3px #e24949 dashed;">Unavailable Video Names</span> <span class="badge bg-primary rounded-pill">{{ videos.count }}</span></h1>
+
+
+        </div>
+
+        {% if videos %}
+            <input   class="form-control border border-secondary" type="text"
+                   name="search" placeholder="Begin to search playlists..."
+                   hx-post="{% url 'search_library' 'unavailable-videos'  %}"
+                   hx-trigger="keyup changed delay:700ms"
+                   hx-target="#search-results"
+                   hx-indicator=".htmx-indicator"
+                    aria-describedby="searchHelp">
+            <div id="searchHelp" class="form-text">For a more extensive name search and filtering, <a href="{% url 'search' %}?mode=videos&type=unavailable">click here</a>.</div>
+
+            <br>
+
+        <div id="search-results" class="row row-cols-1 row-cols-md-4 g-4">
+            {% include 'intercooler/video_cards.html' with videos=videos %}
+        </div>
+        {% else %}
+              <div class="card bg-dark text-white mb-3">
+            <div class="card-body">
+                <div class="d-flex justify-content-center h3">
+                    Nothing here!
+                </div>
+                <div class="d-flex justify-content-center h5">
+                    Any video in your present UnTube collection that goes unavailable on YouTube will all show up here. Note that only
+                    video names will show up here.
+                </div>
+            </div>
+            </div>
+
+        {% endif %}
+        <br>
+
+{% endblock %}

+ 0 - 100
apps/main/templates/videos_home.html

@@ -1,100 +0,0 @@
-{% extends 'base.html' %}
-{% block content %}
-    <br>
-
-<div class="row row-cols-1 row-cols-md-3 g-4" >
-    <div class="col">
-        <a href="{% url 'all_videos' 'all' %}" class="text-decoration-none text-white">
-        <div class="card h-100" style="background-color: #64381a;">
-            <div class="card-body">
-                <h4 class="card-title">All Videos</h4>
-                    <p class="card-text">Everything. From videos in your YouTube playlists to videos in the playlists you Imported.</p>
-            </div>
-        </div>
-        </a>
-    </div>
-    <div class="col">
-        <a href="{% url 'all_videos' 'user-owned' %}" class="text-decoration-none text-white">
-        <div class="card h-100" style="background-color: #1A4464;">
-            <div class="card-body">
-                <h4 class="card-title">Your YouTube Playlists Videos</h4>
-                    <p class="card-text">View a list of all the videos you that are in your YouTube playlists.</p>
-            </div>
-        </div>
-        </a>
-    </div>
-
-    <div class="col">
-        <a href="{% url 'all_videos' 'imported' %}" class="text-decoration-none text-white">
-        <div class="card h-100" style="background-color: #1a645e;">
-            <div class="card-body">
-                <h4 class="card-title">Imported YouTube Playlists Videos</h4>
-                <p class="card-text">View a list of all the videos from external playlists you imported from YouTube.</p>
-            </div>
-        </div>
-        </a>
-    </div>
-    <div class="col">
-        <a href="{% url 'all_videos' 'favorites' %}" class="text-decoration-none text-white">
-        <div class="card h-100" style="background-color: #aa8c2e;">
-            <div class="card-body">
-                <h4 class="card-title">Favorite Videos</h4>
-                <p class="card-text">All the videos you've marked favorite.</p>
-            </div>
-        </div>
-        </a>
-    </div>
-    <div class="col">
-        <a href="{% url 'all_videos' 'watched' %}" class="text-decoration-none text-white">
-        <div class="card h-100" style="background-color: #541a64;">
-            <div class="card-body">
-                <h4 class="card-title">Watched Videos</h4>
-                <p class="card-text">All the videos you've marked watched.</p>
-            </div>
-        </div>
-        </a>
-    </div>
-    <div class="col">
-        <a href="{% url 'all_videos' 'hidden-videos' %}" class="text-decoration-none text-white">
-        <div class="card h-100" style="background-color: #641a29;">
-            <div class="card-body">
-                <h4 class="card-title">Hidden Videos</h4>
-                <p class="card-text">All the videos you've marked hidden inside playlists.</p>
-            </div>
-        </div>
-        </a>
-    </div>
-    <div class="col">
-        <a href="#" class="text-decoration-none text-white">
-        <div class="card h-100" style="background-color: #bd39a7;">
-            <div class="card-body">
-                <h5 class="card-title">Unavailable YouTube Videos</h5>
-                <p class="card-text">List of videos in your collection that went unavailable on YouTube. Note that all details except the video title will have been deleted once a video goes unavailable on YouTube.</p>
-            </div>
-        </div>
-        </a>
-    </div>
-
-    <div class="col">
-        <a href="#" class="text-decoration-none text-white">
-
-        <div class="card h-100" style="background-color: #d04623;">
-            <div class="card-body">
-                <h5 class="card-title">Open a Random Video</h5>
-                <p class="card-text mt-4">
-                    <button type="button" class="btn btn-success dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
-                              From
-                    </button>
-                  <ul class="dropdown-menu">
-                    <li><a class="dropdown-item" href="#">All</a></li>
-                    <li><a class="dropdown-item" href="#">Watched</a></li>
-                    <li><a class="dropdown-item" href="#">Favorites</a></li>
-                  </ul>
-                </p>
-            </div>
-        </div>
-        </a>
-    </div>
-</div>
-<br>
-{% endblock %}

+ 11 - 15
apps/main/templates/view_playlist.html

@@ -33,7 +33,7 @@
                 </div>
             {% else %}
                 <div class="sticky-top mb-3" style="top: 0.5rem;">
-                    {% if not playlist.is_yt_mix and not playlist.playlist_id == "LL" %}
+                    {% if user.profile.auto_check_for_updates and not playlist.is_yt_mix %}
                         <div hx-get="{% url 'update_playlist' playlist.playlist_id 'checkforupdates' %}" hx-trigger="load" hx-swap="outerHTML" id="checkforupdates">
                             <div class="alert alert-info alert-dismissible fade show" role="alert">
                                 Checking playlist for updates...
@@ -442,7 +442,7 @@
                             <h5><span class="text-muted selected-videos-count">0 videos selected</span></h5>
                             <div id="delete-videos-confirm-box">
                                 <h5>You can select videos by clicking any where on the video box. Selected videos will be highlighted red.</h5>
-                                {% if not playlist.confirm_before_deleting %}
+                                {% if not user.profile.confirm_before_deleting %}
                                     <h5>Note: You have set confirm before deleting to False. Buttons below will take effect immediately when clicked.</h5>
                                     <hr>
                                 {% else %}
@@ -458,7 +458,7 @@
                             </div>
                             <div class="d-flex justify-content-start">
                                 <div class="btn-group me-2">
-                                    <button hx-post="{% url 'delete_videos' playlist.playlist_id 'confirm' %}" hx-include="[id='video-checkboxes']" hx-vals='{"confirm before deleting": "{{ playlist.confirm_before_deleting }}"}' hx-target="#delete-videos-confirm-box" type="button" class="btn btn-primary">
+                                    <button hx-post="{% url 'delete_videos' playlist.playlist_id 'confirm' %}" hx-include="[id='video-checkboxes']" hx-vals='{"confirm before deleting": "{{ user.profile.confirm_before_deleting }}"}' hx-target="#delete-videos-confirm-box" type="button" class="btn btn-primary">
                                         Delete Selected
                                     </button>
                                 </div>
@@ -478,7 +478,7 @@
                                     </div>
                                 {% endif %}
                                 <div class="btn-group me-2">
-                                    <button hx-post="{% url 'delete_videos' playlist.playlist_id 'confirm' %}" hx-vals='{"all": "yes", "confirm before deleting": "{{ playlist.confirm_before_deleting }}"}' hx-target="#delete-videos-confirm-box" type="button" class="btn btn-danger">
+                                    <button hx-post="{% url 'delete_videos' playlist.playlist_id 'confirm' %}" hx-vals='{"all": "yes", "confirm before deleting": "{{ user.profile.confirm_before_deleting }}"}' hx-target="#delete-videos-confirm-box" type="button" class="btn btn-danger">
                                         Empty this Playlist
                                     </button>
                                 </div>
@@ -497,7 +497,7 @@
                     <div class="collapse border-danger" id="addVideosCollapse">
                         <div class="card card-body bg-dark text-white">
 
-                            <h5>Add new videos to this playlist <span class="text-muted selected-videos-count">0 videos selected</span></h5>
+                            <h5>Add new videos to this playlist</h5>
 
                             <div class="row d-flex justify-content-start">
 
@@ -523,7 +523,7 @@
 
                                 <div class="btn-group ms-1 mt-1">
                                     <button hx-indicator="#add-videos-loader" hx-post="{% url 'playlist_move_copy_videos' playlist.playlist_id 'copy' %}" hx-include="#playlists-to-move-to, #video-checkboxes" hx-target="#move-copy-videos-box" type="button" class="btn btn-primary">
-                                        Add!
+                                        Add
                                     </button>
                                 </div>
                                 <div id="add-videos-box" class="d-flex align-items-end ms-2">
@@ -563,15 +563,15 @@
                             <div class="d-flex justify-content-start mt-2">
 
                                 <div class="btn-group ms-1 mt-1">
-                                    <button hx-indicator="#add-videos-loader" hx-post="{% url 'playlist_move_copy_videos' playlist.playlist_id 'copy' %}" hx-include="#playlists-to-move-to, #video-checkboxes" hx-target="#move-copy-videos-box" type="button" class="btn btn-light">
-                                        Create!
+                                    <button hx-indicator="#create-playlist-loader" hx-post="{% url 'playlist_move_copy_videos' playlist.playlist_id 'copy' %}" hx-include="#playlists-to-move-to, #video-checkboxes" hx-target="#move-copy-videos-box" type="button" class="btn btn-primary">
+                                        Create
                                     </button>
                                 </div>
                                 <div id="add-videos-box" class="d-flex align-items-end ms-2">
                                 </div>
-                                    <div class="htmx-indicator d-flex align-items-center" id="add-videos-loader">
+                                    <div class="htmx-indicator d-flex align-items-center" id="create-playlist-loader">
                                         <img src="{% static 'svg-loaders/grid.svg' %}" width="25" height="25" class="ms-2 mt-2">
-                                        <span class="mt-2 ms-2 text-warning">Adding videos, please wait... </span>
+                                        <span class="mt-2 ms-2 text-warning">Creating playlist, please wait... </span>
                                     </div>
                             </div>
 
@@ -753,10 +753,6 @@
                 removeItemButton: true,
             });
 
-            BackgroundCheck.init({
-                targets: '.ui',
-                images: '.ui-img'
-            });
         });
 
         $(function () {
@@ -867,7 +863,7 @@
         document.getElementById('manageBtn').addEventListener('click', function () {                document.getElementById("delete-videos-confirm-box").innerHTML = "";
             document.getElementById("delete-videos-confirm-box").innerHTML = `
                 <h5>You can select videos by clicking any where on the video box. Selected videos will be highlighted red.</h5>
-                {% if not playlist.confirm_before_deleting %}
+                {% if not user.profile.confirm_before_deleting %}
                     <h5>Note: You have set confirm before deleting to False. Buttons below will take effect immediately when clicked.</h5>
                     <hr>
                 {% else %}

+ 24 - 5
apps/main/templates/view_video.html

@@ -24,6 +24,7 @@
             </div>
             <div class="card text-white bg-dark" style="max-width: 100%;">
                 <div class="row g-0">
+                    {% if not video.is_unavailable_on_yt and not video.was_deleted_on_yt %}
                     <div class="col-md-4 p-3">
                         <img  class="img-fluid rounded-3" src="{{ video.thumbnail_url }}" style="max-width:100%; height: auto;   object-fit: cover;">
                         <span class="d-flex justify-content-center">
@@ -44,7 +45,8 @@
                             </button>
                         </span>
                     </div>
-                    <div class="col-md-8">
+                    {% endif %}
+                    <div class="col{% if not video.is_unavailable_on_yt and not video.was_deleted_on_yt %}-md-8{% endif %}">
                         <div class="card-body">
                             <div class="row d-flex justify-content-between">
                                 <h2 class="card-title text-white col-10">
@@ -52,10 +54,22 @@
                                     <button class="btn btn-light btn-sm ms-2" onclick='document.getElementById("user-label-alert").style.display = "block";'>
                                         <i class="fas fa-pencil-alt" aria-hidden="true"></i>
                                     </button>
-
+                                    {% if video.is_unavailable_on_yt or video.was_deleted_on_yt %}
+                                    <button class="btn btn-dark" type="button" hx-get="{% url 'mark_video_favorite' video.video_id %}" hx-target="#video-fav">
+    <div id="video-fav">
+        {% if video.is_favorite %}
+            <i class="fas fa-heart" style="color: #fafa06"></i>
+        {% else %}
+            <i class="far fa-heart"></i>
+        {% endif %}
+    </div>
+</button>
+                                    {% endif %}
                                     <br><small class="h4">{% if video.user_label %}a.k.a <span style="border-bottom: 3px #ffffff dashed;"> {{ video.user_label }}</span>{% endif %}</small>
+
                                 </h2>
                             </div>
+                            {% if not video.is_unavailable_on_yt and not video.was_deleted_on_yt %}
                             <h6>by <a href="{% url 'search' %}?mode=videos&channel={{ video.channel_name }}" style="text-decoration: none; color: white"><span style="border-bottom: 3px #e35959 dashed;">{{ video.channel_name }}</span></a></h6>
                             <p class="card-text">
                                 {% if video.description %}
@@ -67,9 +81,11 @@
                                     <h5>No description</h5>
                                 {% endif %}
                             </p>
+                            {% endif %}
 
 
                             <h6 class="h5 text-uppercase overflow-auto text-black-50">
+                                {% if not video.is_unavailable_on_yt and not video.was_deleted_on_yt %}
                                 <a style="text-decoration: none" data-bs-toggle="collapse" href="#{{ video.video_id }}DurationCollapse" role="button" aria-expanded="false" aria-controls="{{ video.video_id }}DurationCollapse">
                                     <span class="badge bg-success mb-1">{{ video.duration }}</span>
                                 </a>
@@ -82,14 +98,17 @@
                                         </div>
                                     </div>
                                 </div>
+                                    {% endif %}
                                 <small>
+                                {% if not video.is_unavailable_on_yt and not video.was_deleted_on_yt %}
                                     {% if video.has_cc %}<span class="badge bg-danger mb-1">CC</span>{% endif %}
                                     {% if video.published_at %}<span class="badge bg-secondary mb-1">Video uploaded on {{ video.published_at }}</span>{% endif %}
                                     <span class="badge bg-primary text-white mb-1"><i class="fas fa-eye"></i> {% if video.view_count == -1 %}HIDDEN{% else %}{{ video.view_count|intcomma }}{% endif %}</span>
-                                    <span class="badge bg-warning text-black-50 mb-1"><i class="fas fa-thumbs-up"></i> {% if video.like_count == -1 %}HIDDEN{% else %}{{ video.like_count|intcomma }}{% endif %}</span>
+                                    <span class="badge bg-warning text-black-50 mb-1"><i class="fas fa-thumbs-up" {% if video.liked %}style="color: dodgerblue"{% endif %}></i> {% if video.like_count == -1 %}HIDDEN{% else %}{{ video.like_count|intcomma }}{% endif %}</span>
                                     <span class="badge bg-warning text-black-50 mb-1"><i class="fas fa-thumbs-down"></i> {% if video.dislike_count == -1 %}HIDDEN{% else %}{{ video.dislike_count|intcomma }}{% endif %}</span>
                                     <span class="badge bg-info text-black-50 mb-1"><i class="fas fa-comments"></i> {% if video.comment_count == -1 %}HIDDEN{% else %}{{ video.comment_count|intcomma }}{% endif %} </span>
-                                    {% if video.is_unavailable_on_yt or video.was_deleted_on_yt %}<span class="badge bg-light text-black-50 mb-1">UNAVAILABLE</span>{% endif %}
+                                {% endif %}
+                                    {% if video.is_unavailable_on_yt or video.was_deleted_on_yt %}<span class="badge bg-danger text-dark mb-1">UNAVAILABLE</span>{% endif %}
                                     <span class="badge bg-light text-black-50 mb-1"><a href="#found-in" style="text-decoration: none; color: grey"> Found in {{ video.playlists.all.count }} playlist{% if video.playlists.all.count > 1 %}s{% endif %}</a></span>
                                     {% if video.is_marked_as_watched %}
                                         <span class="badge bg-dark text-white" >
@@ -101,7 +120,7 @@
                                 </small>
 
                             </h6>
-                            <p class="card-text text-white-50"><small>Last updated {{ video.video_details_modified_at|naturalday }}</small> &bullet; <small>{{ video.num_of_accesses }} clicks </small></p>                        </div>
+                            <p class="card-text text-white-50"><small>Last updated {{ video.video_details_modified_at|naturalday }}</small> &bullet; <small>{{ video.num_of_accesses }} views </small></p>                        </div>
                     </div>
                 </div>
             </div>

+ 20 - 2
apps/main/util.py

@@ -2,9 +2,11 @@ import datetime
 import humanize
 import re
 
-
 # given amount of seconds makes it into this 54 MINUTES AND 53 SECONDS (from humanize) then
 # perform a bunch of replace operations to make it look like 54mins. 53secs.
+import pytz
+
+
 def getHumanizedTimeString(seconds):
     return humanize.precisedelta(
         datetime.timedelta(seconds=seconds)).upper(). \
@@ -72,4 +74,20 @@ def generateWatchingMessage(playlist):
     Takes in the playlist object and calculates the watch time left by looping over unwatched video
     and using their durations
     """
-    pass
+    pass
+
+
+def increment_tag_views(playlist_tags):
+    """
+    Increments playlist tag overall views and views per week. If its been a week, views per week is reset to
+    zero.
+    """
+    for tag in playlist_tags:
+        # reset tag views if its been a week
+        if tag.last_views_reset + datetime.timedelta(days=7) < datetime.datetime.now(pytz.utc):
+            tag.times_viewed_per_week = 0
+            tag.last_views_reset = datetime.datetime.now(pytz.utc)
+        else:
+            tag.times_viewed_per_week += 1
+        tag.times_viewed += 1
+        tag.save(update_fields=['times_viewed', 'last_views_reset', 'times_viewed_per_week'])

+ 28 - 23
apps/main/views.py

@@ -59,10 +59,7 @@ def home(request):
         return render(request, "import_in_progress.html")
     ##################################
 
-    user_playlists = request.user.playlists.filter(is_in_db=True)
-    total_num_playlists = user_playlists.count()
-    user_playlists = user_playlists.filter(num_of_accesses__gt=0).order_by(
-        "-num_of_accesses")
+    playlist_tags = request.user.playlist_tags.order_by('-times_viewed')
 
     videos = request.user.videos.filter(Q(is_unavailable_on_yt=False) & Q(was_deleted_on_yt=False))
 
@@ -70,7 +67,7 @@ def home(request):
         'channel_name').annotate(channel_videos_count=Count('video_id'))
 
     return render(request, 'home.html', {"channel_found": channel_found,
-                                         "user_playlists": user_playlists,
+                                         "playlist_tags": playlist_tags,
                                          "watching": watching,
                                          "recently_accessed_playlists": recently_accessed_playlists,
                                          "recently_added_playlists": recently_added_playlists,
@@ -93,7 +90,7 @@ def view_video(request, video_id):
     if request.user.videos.filter(video_id=video_id).exists():
         video = request.user.videos.get(video_id=video_id)
 
-        if video.is_unavailable_on_yt or video.was_deleted_on_yt:
+        if video.is_unavailable_on_yt:
             messages.error(request, "Video went private/deleted on YouTube!")
             return redirect('home')
 
@@ -135,15 +132,18 @@ def view_playlist(request, playlist_id):
     # specific playlist requested
     if user_profile.playlists.filter(Q(playlist_id=playlist_id) & Q(is_in_db=True)).exists():
         playlist = user_profile.playlists.get(playlist_id__exact=playlist_id)
+        playlist_tags = playlist.tags.all()
 
-        # if its been 30 days since the last playlist visit, force refresh the playlist
-        if datetime.datetime.now(pytz.utc) - playlist.last_accessed_on > datetime.timedelta(days=15):
+        # if its been 1 days since the last full scan, force refresh the playlist
+        if playlist.last_full_scan_at + datetime.timedelta(days=2) < datetime.datetime.now(pytz.utc):
             playlist.has_playlist_changed = True
+            print("ITS BEEN 15 DAYS, FORCE REFRESHING PLAYLIST")
 
-        # only note down that the playlist as been viewed when 5mins has passed since the last access
-        if playlist.last_accessed_on + datetime.timedelta(minutes=1) < datetime.datetime.now(pytz.utc):
-            playlist.num_of_accesses += 1
+        # only note down that the playlist as been viewed when 30s has passed since the last access
+        if playlist.last_accessed_on + datetime.timedelta(seconds=30) < datetime.datetime.now(pytz.utc):
             playlist.last_accessed_on = datetime.datetime.now(pytz.utc)
+            playlist.num_of_accesses += 1
+            increment_tag_views(playlist_tags)
 
         playlist.save(update_fields=['num_of_accesses', 'last_accessed_on', 'has_playlist_changed'])
     else:
@@ -168,14 +168,11 @@ def view_playlist(request, playlist_id):
     playlist_items = playlist.playlist_items.select_related('video').order_by("video_position")
 
     user_created_tags = Tag.objects.filter(created_by=request.user)
-    playlist_tags = playlist.tags.all()
-
-    for tag in playlist_tags:
-        tag.times_viewed += 1
-        tag.save(update_fields=['times_viewed'])
-
     unused_tags = user_created_tags.difference(playlist_tags)
 
+    if request.user.profile.hide_unavailable_videos:
+        playlist_items.exclude(Q(video__is_unavailable_on_yt=True) & Q(video__was_deleted_on_yt=False))
+
     return render(request, 'view_playlist.html', {"playlist": playlist,
                                                   "playlist_tags": playlist_tags,
                                                   "unused_tags": unused_tags,
@@ -185,6 +182,8 @@ def view_playlist(request, playlist_id):
                                                   })
 
 
+
+
 @login_required
 def tagged_playlists(request, tag):
     tag = get_object_or_404(Tag, created_by=request.user, name=tag)
@@ -201,7 +200,9 @@ def library(request, library_type):
     """
     library_type = library_type.lower()
     watching = False
-    if library_type == "" or library_type == "all":
+    if library_type.lower() == "home":  # displays cards of all playlist types
+        return render(request, 'library.html')
+    elif library_type == "all":
         playlists = request.user.playlists.all().filter(is_in_db=True)
         library_type_display = "All Playlists"
     elif library_type == "user-owned":  # YT playlists owned by user
@@ -221,8 +222,9 @@ def library(request, library_type):
     elif library_type.lower() == "yt-mix":
         playlists = request.user.playlists.all().filter(Q(is_yt_mix=True) & Q(is_in_db=True))
         library_type_display = "Your YouTube Mixes"
-    elif library_type.lower() == "home":  # displays cards of all playlist types
-        return render(request, 'library.html')
+    elif library_type.lower() == "unavailable-videos":
+        videos = request.user.videos.all().filter(Q(is_unavailable_on_yt=False) & Q(was_deleted_on_yt=True))
+        return render(request, "unavailable_videos.html", {"videos": videos})
     elif library_type.lower() == "random":  # randomize playlist
         if request.method == "POST":
             playlists_type = request.POST["playlistsType"]
@@ -271,7 +273,7 @@ def order_playlist_by(request, playlist_id, order_by):
         playlist_items = playlist.playlist_items.select_related('video').order_by("-video__like_count")
     elif order_by == "date-published":
         videos_details = "Sorted by Date Published"
-        playlist_items = playlist.playlist_items.select_related('video').order_by("-published_at")
+        playlist_items = playlist.playlist_items.select_related('video').order_by("published_at")
     elif order_by == "views":
         videos_details = "Sorted by View Count"
         playlist_items = playlist.playlist_items.select_related('video').order_by("-video__view_count")
@@ -304,7 +306,7 @@ def order_playlist_by(request, playlist_id, order_by):
                 playlist_items = recently_updated_videos.order_by("video_position")
     elif order_by == 'unavailable-videos':
         playlist_items = playlist.playlist_items.select_related('video').filter(
-            Q(video__is_unavailable_on_yt=True) & Q(video__was_deleted_on_yt=True))
+            Q(video__is_unavailable_on_yt=False) & Q(video__was_deleted_on_yt=True))
         videos_details = "Sorted by Unavailable Videos"
         display_text = "None of the videos in this playlist have gone unavailable... yet."
     elif order_by == 'channel':
@@ -636,7 +638,7 @@ def load_more_videos(request, playlist_id, order_by, page):
     elif order_by == "popularity":
         playlist_items = playlist.playlist_items.select_related('video').order_by("-video__like_count")
     elif order_by == "date-published":
-        playlist_items = playlist.playlist_items.select_related('video').order_by("-published_at")
+        playlist_items = playlist.playlist_items.select_related('video').order_by("published_at")
     elif order_by == "views":
         playlist_items = playlist.playlist_items.select_related('video').order_by("-video__view_count")
     elif order_by == "has-cc":
@@ -669,6 +671,9 @@ def load_more_videos(request, playlist_id, order_by, page):
         playlist_items = playlist.playlist_items.select_related('video').filter(
             video__channel_name=channel_name).order_by("video_position")
 
+    if request.user.profile.hide_unavailable_videos:
+        playlist_items.exclude(Q(video__is_unavailable_on_yt=True) & Q(video__was_deleted_on_yt=False))
+
     return HttpResponse(loader.get_template("intercooler/playlist_items.html")
         .render(
         {

+ 14 - 1
apps/search/templates/search_untube_page.html

@@ -70,9 +70,18 @@
                 </div>
 
             </div>
-            <div class="col-lg-8" id="videos">
+            <div class="col-lg-10" id="videos">
 
                 <div class="row">
+                    <div class="col">
+                        Search in these playlists:
+                        <select class="visually-hidden" onchange="triggerSubmit()"
+                            id="choices-playlists" name="playlist-ids" placeholder="Add playlists to search within" multiple>
+                            {% for playlist in user.profile.get_playlists_list %}
+                                <option value="{{ playlist.playlist_id }}" {% if playlist.playlist_id == playlist_id %}selected{% endif %}>{{ playlist.name }} {% if playlist.user_label %}({{ playlist.user_label }}){% endif %}</option>
+                            {% endfor %}
+                        </select>
+                    </div>
                     <div class="col">
                         Filter by video channels:
                         <select class="visually-hidden" onchange="triggerSubmit()"
@@ -89,6 +98,7 @@
                                 Video type:
                                 <select onchange="triggerSubmit()" class="form-select mt-1" name="videosType">
                                     <option value="All" {% if item_type == "all" %}selected{% endif %}>All</option>
+                                    <option value="Liked" {% if item_type == "liked" %}selected{% endif %}>Liked</option>
                                     <option value="Favorite" {% if item_type == "favorite" %}selected{% endif %}>Favorite</option>
                                     <option value="Watched" {% if item_type == "watched" %}selected{% endif %}>Watched</option>
                                      <option value="Unavailable" {% if item_type == "unavailable" %}selected{% endif %}>Unavailable</option>
@@ -175,6 +185,9 @@
                     removeItemButton: true,
                 });
 
+                var choicesPlaylists = new Choices('#choices-playlists', {
+                    removeItemButton: true,
+                });
                 triggerSubmit();
             });
 

+ 1 - 2
apps/search/urls.py

@@ -4,7 +4,6 @@ from . import views
 urlpatterns = [
     path("", views.search, name="search"),
     path("untube/", views.search_UnTube, name="search_UnTube"),
-    path("playlists/<slug:playlist_type>", views.search_playlists, name="search_playlists"),
-    path("videos/<slug:playlist_type>", views.search_playlists, name="search_playlists"),
+    path("library/<slug:library_type>", views.search_library, name="search_library"),
     path("tagged-playlists/<str:tag>", views.search_tagged_playlists, name="search_tagged_playlists"),
 ]

+ 21 - 9
apps/search/views.py

@@ -106,7 +106,9 @@ def search_UnTube(request):
         videos_type = bleach.clean(request.POST["videosType"])
 
         all_videos = request.user.videos.filter(is_unavailable_on_yt=False)
-        if videos_type == "Favorite":
+        if videos_type == "Liked":
+            all_videos = all_videos.filter(liked=True)
+        elif videos_type == "Favorite":
             all_videos = all_videos.filter(is_favorite=True)
         elif videos_type == "Watched":
             all_videos = all_videos.filter(is_marked_as_watched=True)
@@ -142,6 +144,10 @@ def search_UnTube(request):
         if 'has-cc' in request.POST:
             videos = videos.filter(has_cc=True)
 
+        if 'playlist-ids' in request.POST:
+            playlist_ids = request.POST.getlist('playlist-ids')
+            videos = videos.filter(playlists__playlist_id__in=playlist_ids)
+
         return HttpResponse(loader.get_template("intercooler/search_untube_results.html")
                             .render({"videos": videos,
                                      "view_mode": "videos",
@@ -151,50 +157,56 @@ def search_UnTube(request):
 
 @login_required
 @require_POST
-def search_playlists(request, playlist_type):
+def search_library(request, library_type):
     # print(request.POST)  # prints <QueryDict: {'search': ['aa']}>
 
     search_query = request.POST["search"]
     watching = False
 
     playlists = None
-    if playlist_type == "all":
+    if library_type == "all":
         try:
             playlists = request.user.playlists.all().filter(Q(name__startswith=search_query) | Q(user_label__startswith=search_query) & Q(is_in_db=True))
         except:
             playlists = request.user.playlists.all()
-    elif playlist_type == "user-owned":  # YT playlists owned by user
+    elif library_type == "user-owned":  # YT playlists owned by user
         try:
             playlists = request.user.playlists.filter(
                 Q(name__startswith=search_query) | Q(user_label__startswith=search_query) & Q(is_user_owned=True) & Q(is_in_db=True))
         except:
             playlists = request.user.playlists.filter(Q(is_user_owned=True) & Q(is_in_db=True))
-    elif playlist_type == "imported":  # YT playlists (public) owned by others
+    elif library_type == "imported":  # YT playlists (public) owned by others
         try:
             playlists = request.user.playlists.filter(
                 Q(name__startswith=search_query) | Q(user_label__startswith=search_query) & Q(is_user_owned=False) & Q(is_in_db=True))
         except:
             playlists = request.user.playlists.filter(Q(is_user_owned=True) & Q(is_in_db=True))
-    elif playlist_type == "favorites":  # YT playlists (public) owned by others
+    elif library_type == "favorites":  # YT playlists (public) owned by others
         try:
             playlists = request.user.playlists.filter(
                 Q(name__startswith=search_query) | Q(user_label__startswith=search_query) & Q(is_favorite=True) & Q(is_in_db=True))
         except:
             playlists = request.user.playlists.filter(Q(is_favorite=True) & Q(is_in_db=True))
-    elif playlist_type in ["watching", "plan-to-watch"]:
+    elif library_type in ["watching", "plan-to-watch"]:
         try:
             playlists = request.user.playlists.filter(
                 Q(name__startswith=search_query) | Q(user_label__startswith=search_query) & Q(marked_as=playlist_type) & Q(is_in_db=True))
         except:
             playlists = request.user.playlists.all().filter(Q(marked_as=playlist_type) & Q(is_in_db=True))
-        if playlist_type == "watching":
+        if library_type == "watching":
             watching = True
-    elif playlist_type == "yt-mix":  # YT playlists owned by user
+    elif library_type == "yt-mix":  # YT playlists owned by user
         try:
             playlists = request.user.playlists.filter(
                 Q(name__startswith=search_query) | Q(user_label__startswith=search_query) & Q(is_yt_mix=True) & Q(is_in_db=True))
         except:
             playlists = request.user.playlists.filter(Q(is_yt_mix=True) & Q(is_in_db=True))
+    elif library_type == 'unavailable-videos':
+        try:
+            videos = request.user.videos.filter(Q(is_unavailable_on_yt=False) & Q(was_deleted_on_yt=True)).filter(Q(name__startswith=search_query) | Q(user_label__startswith=search_query))
+        except:
+            videos = request.user.videos.filter(Q(is_unavailable_on_yt=False) & Q(was_deleted_on_yt=True))
+        return HttpResponse(loader.get_template("intercooler/video_cards.html").render({"videos": videos}))
 
     return HttpResponse(loader.get_template("intercooler/playlists.html")
                         .render({"playlists": playlists,

+ 18 - 0
apps/users/migrations/0011_profile_auto_check_for_updates.py

@@ -0,0 +1,18 @@
+# Generated by Django 3.2.3 on 2021-07-29 23:28
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('users', '0010_profile_enable_gradient_bg'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='profile',
+            name='auto_check_for_updates',
+            field=models.BooleanField(default=False),
+        ),
+    ]

+ 18 - 0
apps/users/migrations/0012_alter_profile_hide_unavailable_videos.py

@@ -0,0 +1,18 @@
+# Generated by Django 3.2.3 on 2021-07-31 03:39
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('users', '0011_profile_auto_check_for_updates'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='profile',
+            name='hide_unavailable_videos',
+            field=models.BooleanField(default=True),
+        ),
+    ]

+ 9 - 3
apps/users/models.py

@@ -30,13 +30,16 @@ class Profile(models.Model):
     user_summary = models.CharField(max_length=300, default="I think my arm is on backward.")
     user_location = models.CharField(max_length=100, default="Hell, Earth")
 
-    # preferences
+    ### GLOBAL preferences ###
+    # site preferences
     open_search_new_tab = models.BooleanField(default=True)  # open search page in new tab by default
     enable_gradient_bg = models.BooleanField(default=False)
 
-    # global playlist preferences (this will make all playlists)
-    hide_unavailable_videos = models.BooleanField(default=False)
+    # playlist preferences (this will apply to all playlists)
+    auto_check_for_updates = models.BooleanField(default=False)
+    hide_unavailable_videos = models.BooleanField(default=True)
     confirm_before_deleting = models.BooleanField(default=True)
+    ###########################
 
     # manage user
     objects = ProfileManager()
@@ -73,6 +76,9 @@ class Profile(models.Model):
 
         return channels_list
 
+    def get_playlists_list(self):
+        return self.user.playlists.all().filter(is_in_db=True)
+
 # as soon as one User object is created, create an associated profile object
 @receiver(post_save, sender=User)
 def create_user_profile(sender, instance, created, **kwargs):

+ 13 - 94
apps/users/templates/settings.html

@@ -60,7 +60,7 @@
                 </div>
               </div>
             <hr>
-                    <a href="#navbar" hx-post="{% url 'update_settings' %}" hx-include="[id='settings-form']" hx-target="#settings-status-div" class="btn btn-success">Update</a>
+                    <a href="{% url 'update_settings' %}" class="btn btn-success">Update</a>
 
             </div>
           </div>
@@ -68,15 +68,11 @@
         </div>
         <div class="col-md-8">
 
-        <div id="settings-status-div" class="text-dark">
-
-        </div>
-
           <div class="card bg-dark text-white mb-3">
             <div class="card-body">
-                <div id="settings-form">
-
-                <div class="row">
+                <form action="{% url 'update_settings' %}" method="post">
+                    {% csrf_token %}
+                        <div class="row">
                 <div class="col-sm-3">
                   <h6 class="mb-0">Username</h6>
                 </div>
@@ -123,34 +119,36 @@
                         </div>
 
                         <div class="mb-3 form-check form-switch">
-                        <input class="form-check-input" name="auto refresh playlists" type="checkbox" id="flexSwitchCheckDefault">
-                        <label class="form-check-label" for="flexSwitchCheckDefault">Automatically check for playlist updates on visit</label>
+                        <input class="form-check-input" name="auto refresh playlists" type="checkbox" id="auto-update-playlists" {% if user.profile.auto_check_for_updates %}checked{% endif %}>
+                        <label class="form-check-label" for="auto-update-playlists" >Automatically check for playlist updates on visit (this might slow down the playlist page for a bit)</label>
                         </div>
 
                         <div class="mb-3 form-check form-switch">
-                        <input class="form-check-input" name="hide videos" type="checkbox" id="hide-videos" {% if profile.hide_unavailable_videos %}checked{% endif %}>
+                        <input class="form-check-input" name="hide videos" type="checkbox" id="hide-videos" {% if user.profile.hide_unavailable_videos %}checked{% endif %}>
                         <label class="form-check-label" for="hide-videos">Hide deleted/private videos</label>
                         </div>
 
 
                         <div class="mb-3 form-check form-switch">
-                        <input class="form-check-input" name="confirm before deleting" type="checkbox" id="confirm-before-delete" {% if profile.confirm_before_deleting  %}checked{% endif %}>
+                        <input class="form-check-input" name="confirm before deleting" type="checkbox" id="confirm-before-delete" {% if user.profile.confirm_before_deleting  %}checked{% endif %}>
                         <label class="form-check-label" for="confirm-before-delete">Confirm before deleting</label>
                         </div>
 
                     </div>
                 </div>
                 <hr>
-            </div>
-
 
               <div class="row">
                 <div class="col-sm-12">
-                    <a href="#navbar" hx-post="{% url 'update_settings' %}" hx-include="[id='settings-form']" hx-target="#settings-status-div" class="btn btn-success">Save</a>
+
+                    <button type="submit" class="btn btn-success">Save</button>
                     <a class="btn btn-outline-danger" href="{% url 'delete_account' %}">Delete UnTube account</a>
 
                 </div>
               </div>
+                </form>
+
+
 
             </div>
           </div>
@@ -180,83 +178,4 @@
 
     </div>
 </div>
-
-<!--
-<div class="container-fluid">
-
-    <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
-
-        <h1 class="h2">Settings</h1>
-        <span><small>Logged in as <b>{{ user.username }}</b></small></span>
-
-    </div>
-
-        <div id="settings-status-div" class="text-dark">
-
-        </div>
-
-        <div id="settings-form">
-            <div class="mb-3">
-            <label for="username" class="form-label">Username</label>
-            <input type="text" class="form-control" name="username" id="username" value="{{ user.username }}">
-            </div>
-
-            <fieldset disabled>
-            <div class="mb-3">
-            <label for="email" class="form-label">Email Address</label>
-            <input type="email" class="form-control" id="email" aria-describedby="emailHelp" value="{{ user.email }}">
-            <div id="emailHelp" class="form-text">This is the google account you logged in with.</div>
-            </div>
-
-            <div class="mb-3">
-            <label for="fullname" class="form-label">Full Name</label>
-            <input type="text" class="form-control" id="fullname" value="{{ user.get_full_name }}">
-            </div>
-
-            <div class="mb-3">
-            <label for="ytchannelid" class="form-label">YouTube Channel ID</label>
-            <input type="text" class="form-control" id="ytchannelid" aria-describedby="emailHelp" value="{{ user.profile.yt_channel_id }}">
-            </div>
-
-            <div class="mb-3">
-            <label for="accesstoken" class="form-label">Access Token</label>
-            <input type="text" class="form-control" id="accesstoken" value="{{ user.profile.access_token }}">
-            </div>
-
-            <div class="mb-3">
-            <label for="refreshtoken" class="form-label">Refresh Token</label>
-            <input type="text" class="form-control" id="refreshtoken" value="{{ user.profile.refresh_token }}">
-            </div>
-
-            <div class="mb-3">
-            <label for="expiresat" class="form-label">Expires At</label>
-            <input type="datetime-local" class="form-control" id="expiresat" value="{{ user.profile.expires_at }}">
-            </div>
-            </fieldset>
-
-            <div class="mb-3 form-check form-switch">
-            <input class="form-check-input" name="auto refresh playlists" type="checkbox" id="flexSwitchCheckDefault">
-            <label class="form-check-label" for="flexSwitchCheckDefault">Automatically refresh playlists on visit</label>
-            </div>
-
-            <div class="mb-3 form-check form-switch">
-            <input class="form-check-input" name="hide videos" type="checkbox" id="flexSwitchCheckChecked" checked>
-            <label class="form-check-label" for="flexSwitchCheckChecked">Hide deleted/private videos</label>
-            </div>
-
-
-            <div class="mb-3 form-check form-switch">
-            <input class="form-check-input" name="confirm before deleting" type="checkbox" id="flexSwitchCheckChecked" checked>
-            <label class="form-check-label" for="flexSwitchCheckChecked">Confirm before deleting</label>
-            </div>
-            </div>
-
-        <div>
-            <a class="btn btn-outline-danger" href="{% url 'delete_account' %}">Delete account</a>
-            <button type="button" hx-post="{% url 'update_settings' %}" hx-include="[id='settings-form']" hx-target="#settings-status-div" class="btn btn-success">Save</button>
-        </div>
-
-</div>
-
--->
 {% endblock %}

+ 23 - 4
apps/users/views.py

@@ -74,15 +74,17 @@ def update_settings(request):
     user = request.user
     username_input = request.POST['username'].strip()
     message_content = "Saved!"
-    message_type = "success"
+    #message_type = "success"
     if username_input != user.username:
         if User.objects.filter(username__exact=username_input).count() != 0:
-            message_type = "danger"
+            #message_type = "danger"
             message_content = f"Username {request.POST['username'].strip()} already taken"
+            messages.error(request, message_content)
         else:
             user.username = request.POST['username'].strip()
             # user.save()
             message_content = f"Username updated to {username_input}!"
+            messages.success(request, message_content)
 
     if 'open search in new tab' in request.POST:
         user.profile.open_search_new_tab = True
@@ -94,10 +96,27 @@ def update_settings(request):
     else:
         user.profile.enable_gradient_bg = False
 
+    if 'auto refresh playlists' in request.POST:
+        user.profile.auto_check_for_updates = True
+    else:
+        user.profile.auto_check_for_updates = False
+
+    if 'confirm before deleting' in request.POST:
+        user.profile.confirm_before_deleting = True
+    else:
+        user.profile.confirm_before_deleting = False
+
+    if 'hide videos' in request.POST:
+        user.profile.hide_unavailable_videos = True
+    else:
+        user.profile.hide_unavailable_videos = False
+
     user.save()
 
-    return HttpResponse(loader.get_template("intercooler/messages.html").render(
-        {"message_type": message_type, "message_content": message_content, "refresh_page": True}))
+    if message_content == "Saved!":
+        messages.success(request, message_content)
+
+    return redirect('settings')
 
 
 @login_required

+ 4 - 2
templates/base.html

@@ -115,7 +115,9 @@
 
         </style>
 
-        <link href="https://fonts.googleapis.com/css2?family=Fredoka+One&family=Open+Sans&display=swap" rel="stylesheet">
+         <link rel="preconnect" href="https://fonts.googleapis.com">
+        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+ <link href="https://fonts.googleapis.com/css2?family=Comfortaa&family=Fredoka+One&display=swap" rel="stylesheet">
 
         <link href="{% static 'fontawesome-free-5.15.3-web/css/all.min.css' %}" rel="stylesheet">
         <link href="{% static 'bootstrap5.0.1/css/bootstrap.min.css' %}" rel="stylesheet">
@@ -125,7 +127,7 @@
         <script src="{% static 'jquery3.6.0/js/jquery-3.6.0.min.js' %}" type="application/javascript"></script>
         <script src="{% static 'bootstrap5.0.1/js/bootstrap.bundle.min.js' %}" type="application/javascript"></script>
             </head>
-    <body class="text-dark" style="font-family: 'Fredoka One', monospace; {% if not user.profile.enable_gradient_bg %}background-color: #FDF4DC;{% endif %}">
+    <body class="text-dark" style="font-family: 'Fredoka One', 'Comfortaa',  sans-serif; {% if not user.profile.enable_gradient_bg %}background-color: #FDF4DC;{% endif %}">
 
 
         {% if user.profile.show_import_page %}