Compare commits
2 Commits
04e282d097
...
c9b4ec26fd
Author | SHA1 | Date | |
---|---|---|---|
c9b4ec26fd | |||
f7d99ee5fc |
105
app.py
105
app.py
@ -40,7 +40,7 @@ app.config.from_object(Config)
|
||||
db.init_app(app)
|
||||
bcrypt.init_app(app)
|
||||
login_manager = LoginManager(app)
|
||||
login_manager.login_view = 'login'
|
||||
login_manager.login_view = 'auth.login'
|
||||
|
||||
@login_manager.user_loader
|
||||
def load_user(user_id):
|
||||
@ -114,8 +114,6 @@ def vote_art(image_id):
|
||||
|
||||
return redirect(url_for('view', content_type='art', id=image_id))
|
||||
|
||||
@app.route('/view/<content_type>/<int:id>', methods=['GET', 'POST'])
|
||||
|
||||
@app.route('/view/<content_type>/<int:id>', methods=['GET', 'POST'])
|
||||
def view(content_type, id):
|
||||
comments = []
|
||||
@ -131,6 +129,13 @@ def view(content_type, id):
|
||||
content = Image.query.get_or_404(id)
|
||||
comments = Comments.query.filter_by(image_id=id).order_by(Comments.comment_date.desc()).all()
|
||||
|
||||
if current_user.is_authenticated:
|
||||
existing_view = Views.query.filter_by(image_id=id, username=current_user.username).first()
|
||||
if not existing_view:
|
||||
new_view = Views(image_id=id, username=current_user.username)
|
||||
db.session.add(new_view)
|
||||
db.session.commit()
|
||||
|
||||
search_query = request.args.get('search')
|
||||
page = request.args.get('page', 1, type=int)
|
||||
subscriptions = []
|
||||
@ -157,6 +162,13 @@ def view(content_type, id):
|
||||
content = Video.query.get_or_404(id)
|
||||
comments = Comments.query.filter_by(video_id=id).order_by(Comments.comment_date.desc()).all()
|
||||
|
||||
if current_user.is_authenticated:
|
||||
existing_view = Views.query.filter_by(video_id=id, username=current_user.username).first()
|
||||
if not existing_view:
|
||||
new_view = Views(video_id=id, username=current_user.username)
|
||||
db.session.add(new_view)
|
||||
db.session.commit()
|
||||
|
||||
all_videos = Video.query.order_by(Video.id).all()
|
||||
video_ids = [video.id for video in all_videos]
|
||||
current_index = video_ids.index(id)
|
||||
@ -172,6 +184,13 @@ def view(content_type, id):
|
||||
content = Comic.query.get_or_404(id)
|
||||
comments = Comments.query.filter_by(comic_id=id).order_by(Comments.comment_date.desc()).all()
|
||||
|
||||
if current_user.is_authenticated:
|
||||
existing_view = Views.query.filter_by(image_id=id, username=current_user.username).first()
|
||||
if not existing_view:
|
||||
new_view = Views(image_id=id, username=current_user.username)
|
||||
db.session.add(new_view)
|
||||
db.session.commit()
|
||||
|
||||
comic_pages = ComicPage.query.filter_by(comic_id=id).order_by(ComicPage.page_number).all()
|
||||
|
||||
if not comic_pages:
|
||||
@ -286,8 +305,7 @@ def image_edit(id):
|
||||
|
||||
@app.route('/video_edit/<int:id>', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def video_edit(id):
|
||||
|
||||
async def video_edit(id):
|
||||
video = Video.query.get_or_404(id)
|
||||
|
||||
if video.username != current_user.username:
|
||||
@ -301,7 +319,6 @@ def video_edit(id):
|
||||
form.tags.data = video.tags
|
||||
|
||||
if form.validate_on_submit():
|
||||
|
||||
video.video_name = form.video_name.data
|
||||
video.description = form.description.data
|
||||
video.tags = form.tags.data
|
||||
@ -310,10 +327,15 @@ def video_edit(id):
|
||||
thumbnail_file = form.video_thumbnail.data
|
||||
if allowed_file(thumbnail_file.filename, app.config['ALLOWED_IMAGE_EXTENSIONS']):
|
||||
|
||||
thumbnail_filename = generate_unique_filename(thumbnail_file.filename, app.config['UPLOAD_FOLDER']['thumbnails'])
|
||||
thumbnail_filename = await generate_unique_filename(
|
||||
app.config['UPLOAD_FOLDER']['thumbnails'], 'webp'
|
||||
)
|
||||
thumbnail_path = os.path.join(app.config['UPLOAD_FOLDER']['thumbnails'], thumbnail_filename)
|
||||
|
||||
thumbnail_file.save(thumbnail_path)
|
||||
webp_thumbnail = await convert_to_webp(thumbnail_file)
|
||||
async with aiofiles.open(thumbnail_path, 'wb') as f:
|
||||
await f.write(webp_thumbnail.read())
|
||||
|
||||
video.video_thumbnail_file = thumbnail_filename
|
||||
|
||||
db.session.commit()
|
||||
@ -476,6 +498,40 @@ def videos():
|
||||
query = get_content_query(Video, subscriptions, search_query)
|
||||
pagination = query.paginate(page=page, per_page=10, error_out=False)
|
||||
|
||||
videos_with_views = []
|
||||
for video in pagination.items:
|
||||
views_count = db.session.query(func.count(Views.id)).filter(Views.video_id == video.id).scalar()
|
||||
videos_with_views.append({
|
||||
'video': video,
|
||||
'views_count': views_count
|
||||
})
|
||||
|
||||
popular_videos = [
|
||||
{
|
||||
'video': video[0],
|
||||
'views_count': video[1]
|
||||
}
|
||||
for video in db.session.query(Video, func.count(Views.id).label('views_count'))
|
||||
.outerjoin(Views, Views.video_id == Video.id)
|
||||
.group_by(Video.id)
|
||||
.order_by(func.count(Views.id).desc(), Video.cookie_votes.desc())
|
||||
.limit(8)
|
||||
.all()
|
||||
]
|
||||
|
||||
most_viewed_videos = [
|
||||
{
|
||||
'video': video[0],
|
||||
'views_count': video[1]
|
||||
}
|
||||
for video in db.session.query(Video, func.count(Views.id).label('views_count'))
|
||||
.outerjoin(Views, Views.video_id == Video.id)
|
||||
.group_by(Video.id)
|
||||
.order_by(func.count(Views.id).desc())
|
||||
.limit(8)
|
||||
.all()
|
||||
]
|
||||
|
||||
videos_tags = [video.tags for video in Video.query.all() if video.tags]
|
||||
all_tags = [tag.strip() for tags in videos_tags for tag in tags.split(',')]
|
||||
sorted_tags = sorted(set(all_tags))
|
||||
@ -487,12 +543,14 @@ def videos():
|
||||
|
||||
return render_template(
|
||||
'videos.html',
|
||||
videos=pagination.items,
|
||||
videos=videos_with_views,
|
||||
pagination=pagination,
|
||||
user_cookies=user_cookies,
|
||||
search_query=search_query,
|
||||
content_type='video',
|
||||
tags=sorted_tags
|
||||
tags=sorted_tags,
|
||||
popular_videos=popular_videos,
|
||||
most_viewed_videos=most_viewed_videos
|
||||
)
|
||||
|
||||
|
||||
@ -889,33 +947,6 @@ def terms_of_use():
|
||||
def publication_rules():
|
||||
return render_template('publication_rules.html')
|
||||
|
||||
@app.route('/shop')
|
||||
@login_required
|
||||
def shop():
|
||||
|
||||
items = Item.query.filter_by(visible=True).all()
|
||||
user_cookies = Cookies.query.filter_by(username=current_user.username).first().cookies if Cookies.query.filter_by(username=current_user.username).first() else 0
|
||||
user_item_ids = {ui.item_id for ui in UserItem.query.filter_by(username=current_user.username).all()}
|
||||
return render_template('shop.html', items=items, user=current_user, user_cookies=user_cookies, user_item_ids=user_item_ids)
|
||||
|
||||
@app.route('/buy_item/<int:item_id>', methods=['POST'])
|
||||
@login_required
|
||||
def buy_item(item_id):
|
||||
username = current_user.username
|
||||
user_cookies = Cookies.query.filter_by(username=username).first()
|
||||
item = Item.query.get(item_id)
|
||||
|
||||
if not user_cookies or not item or not item.visible or user_cookies.cookies < item.price:
|
||||
return redirect(url_for('shop'))
|
||||
|
||||
if UserItem.query.filter_by(username=username, item_id=item.id).first():
|
||||
return redirect(url_for('shop'))
|
||||
|
||||
user_cookies.cookies -= item.price
|
||||
db.session.add(UserItem(username=username, item_id=item.id))
|
||||
db.session.commit()
|
||||
return redirect(url_for('shop'))
|
||||
|
||||
if __name__ == '__main__':
|
||||
with app.app_context():
|
||||
db.create_all()
|
||||
|
@ -1,12 +1,14 @@
|
||||
$dark-violet: #0D0C1C;
|
||||
$violet: #3c3882;
|
||||
$violet: #3C3882;
|
||||
$light-violet: #8784C9;
|
||||
@import url('https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,200..1000;1,200..1000&family=Playwrite+IT+Moderna:wght@100..400&display=swap');
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap');
|
||||
|
||||
body {
|
||||
background-color: #05040A;
|
||||
font-family: Nunito, sans-serif;
|
||||
}
|
||||
|
||||
.container {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
@ -31,6 +33,7 @@ body{
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.img-new-content {
|
||||
width: 1502px;
|
||||
height: 423px;
|
||||
@ -54,9 +57,11 @@ body{
|
||||
gap: 20px;
|
||||
width: 1502px;
|
||||
height: 631px;
|
||||
left: 209px;
|
||||
position: absolute;
|
||||
top: 653px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.img-popular-content {
|
||||
@ -80,10 +85,13 @@ body{
|
||||
gap: 20px;
|
||||
width: 1502px;
|
||||
height: 631px;
|
||||
left: 209px;
|
||||
position: absolute;
|
||||
top: 1340px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.img-viewed-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -97,7 +105,6 @@ body{
|
||||
top: 1617px;
|
||||
}
|
||||
|
||||
|
||||
.popular-categories {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@ -108,9 +115,11 @@ body{
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
top: 2095px;
|
||||
left: 210px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.img-popular-categories {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@ -196,7 +205,7 @@ body{
|
||||
}
|
||||
|
||||
.view-more-button:hover {
|
||||
background-color: #3C3882;
|
||||
background-color: $violet;
|
||||
transition: background-color 0.3s ease, color 0.3s ease;
|
||||
}
|
||||
|
||||
@ -229,14 +238,13 @@ body{
|
||||
}
|
||||
|
||||
.img-view-more-button:hover {
|
||||
background-color: #3C3882;
|
||||
background-color: $violet;
|
||||
transition: background-color 0.3s ease, color 0.3s ease;
|
||||
}
|
||||
|
||||
.img-view-more-button:hover .new-context-button-text {
|
||||
color: $light-violet;
|
||||
transition: color 0.3s ease;
|
||||
|
||||
}
|
||||
|
||||
.new-context-button-text {
|
||||
@ -246,9 +254,11 @@ body{
|
||||
font-size: 16px;
|
||||
line-height: 100%;
|
||||
letter-spacing: 0%;
|
||||
color: #3C3882;
|
||||
color: $violet;
|
||||
}
|
||||
|
||||
/* navbar */
|
||||
|
||||
.navbar {
|
||||
width: 100%;
|
||||
max-width: 1500px;
|
||||
@ -259,16 +269,19 @@ body{
|
||||
padding: 0 20px;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.navbar-wrapper {
|
||||
width: 100%;
|
||||
background: $dark-violet;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 307px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -281,12 +294,14 @@ body{
|
||||
position: relative;
|
||||
transition: border-color 0.3s ease;
|
||||
}
|
||||
|
||||
.search-icon-container {
|
||||
position: relative;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.search-icon,
|
||||
.search-hover-icon {
|
||||
width: 24px;
|
||||
@ -296,9 +311,11 @@ body{
|
||||
left: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.search-hover-icon {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.search-container:hover .search-hover-icon,
|
||||
.search-container:focus-within .search-hover-icon {
|
||||
opacity: 1;
|
||||
@ -320,11 +337,11 @@ body{
|
||||
}
|
||||
|
||||
.search-container:hover {
|
||||
border-color: #3C3882;
|
||||
border-color: $violet;
|
||||
}
|
||||
|
||||
.search-container:focus-within {
|
||||
border-color: #3C3882;
|
||||
border-color: $violet;
|
||||
}
|
||||
|
||||
.icon-container {
|
||||
@ -338,11 +355,13 @@ body{
|
||||
height: 24px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.tray-icon {
|
||||
width: 11px;
|
||||
height: 7px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.translate-btn {
|
||||
position: relative;
|
||||
width: 23px;
|
||||
@ -357,6 +376,7 @@ body{
|
||||
padding: 15px;
|
||||
transition: border-color 0.3s ease, transform 0.3s ease, opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.translate-icon,
|
||||
.translate-hover-icon {
|
||||
width: 24px;
|
||||
@ -367,9 +387,11 @@ body{
|
||||
transform: translate(-50%, -50%);
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.translate-hover-icon {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.translate-btn:hover .translate-hover-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
@ -377,9 +399,11 @@ body{
|
||||
.translate-btn:hover .translate-icon {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.translate-btn:hover {
|
||||
border-color: #3C3882;
|
||||
border-color: $violet;
|
||||
}
|
||||
|
||||
.overlay-icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
@ -389,6 +413,7 @@ body{
|
||||
height: 20px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.menu {
|
||||
display: flex;
|
||||
gap: 22px;
|
||||
@ -398,25 +423,30 @@ body{
|
||||
padding-left: 60px;
|
||||
padding-right: 60px;
|
||||
}
|
||||
|
||||
.menu a {
|
||||
text-decoration: none;
|
||||
color: $light-violet;
|
||||
font-size: 16px;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.menu a:hover {
|
||||
color: #3C3882;
|
||||
color: $violet;
|
||||
}
|
||||
|
||||
.auth-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.discord-icon-container {
|
||||
position: relative;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
}
|
||||
|
||||
.discord-icon,
|
||||
.discord-hover-icon {
|
||||
width: 42px;
|
||||
@ -426,15 +456,19 @@ body{
|
||||
left: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.discord-hover-icon {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.discord-icon-container:hover .discord-hover-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.discord-icon-container:hover .discord-icon {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.login-btn {
|
||||
width: 87px;
|
||||
height: 42px;
|
||||
@ -451,17 +485,19 @@ body{
|
||||
margin-left: 10px;
|
||||
transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
|
||||
}
|
||||
|
||||
.login-btn:hover {
|
||||
background-color: #3C3882;
|
||||
background-color: $violet;
|
||||
color: $dark-violet;
|
||||
border-color: #3C3882;
|
||||
border-color: $violet;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: 0;
|
||||
background: $dark-violet;
|
||||
border: 1px solid #3C3882;
|
||||
border: 1px solid $violet;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
display: none;
|
||||
@ -469,6 +505,7 @@ flex-direction: column;
|
||||
width: 150px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
padding: 10px 15px;
|
||||
font-size: 14px;
|
||||
@ -477,16 +514,21 @@ color: $light-violet;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s ease, color 0.3s ease;
|
||||
}
|
||||
|
||||
.dropdown-item:hover {
|
||||
background: #3C3882;
|
||||
background: $violet;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* tags-list */
|
||||
|
||||
.tags-container {
|
||||
width: 1500px;
|
||||
height: 35px;
|
||||
position: absolute;
|
||||
top: 192px;
|
||||
left: 210px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
@ -509,7 +551,7 @@ color: white;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #3C3882;
|
||||
background-color: $violet;
|
||||
border: none;
|
||||
color: $light-violet;
|
||||
margin: 0;
|
||||
@ -527,7 +569,7 @@ color: white;
|
||||
justify-content: center;
|
||||
border: 2px solid $light-violet;
|
||||
background-color: transparent;
|
||||
color: #3C3882;
|
||||
color: $violet;
|
||||
margin-left: 10px;
|
||||
gap: 5px;
|
||||
position: relative;
|
||||
@ -541,6 +583,9 @@ color: white;
|
||||
right: 0;
|
||||
background: linear-gradient(to right, rgba(5, 4, 10, 0) 30%, rgba(5, 4, 10, 0.5) 60%, #05040A 100%);
|
||||
}
|
||||
|
||||
/* cards */
|
||||
|
||||
.img-cards-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, 1fr);
|
||||
@ -549,6 +594,7 @@ color: white;
|
||||
height: 708px;
|
||||
margin-top: 60px;
|
||||
}
|
||||
|
||||
.img-card {
|
||||
width: 225px;
|
||||
height: 344px;
|
||||
@ -556,6 +602,7 @@ color: white;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.img-card-cover {
|
||||
width: 100%;
|
||||
height: 280px;
|
||||
@ -577,12 +624,35 @@ color: white;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-cover {
|
||||
width: 100%;
|
||||
height: 180px;
|
||||
background: #1D1C2E;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-cover img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.card-cover video.preview-video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.card-info {
|
||||
@ -614,6 +684,7 @@ color: white;
|
||||
font-size: 14px;
|
||||
color: $light-violet;
|
||||
}
|
||||
|
||||
.img-small-cards-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
@ -621,11 +692,14 @@ color: white;
|
||||
width: 100%;
|
||||
margin-top: 60px;
|
||||
}
|
||||
|
||||
.img-small-card-cover {
|
||||
width: 189px;
|
||||
height: 250px;
|
||||
background: #1D1C2E;
|
||||
}
|
||||
|
||||
|
||||
.img-small-card {
|
||||
width: 189px;
|
||||
height: 314px;
|
||||
@ -633,6 +707,7 @@ color: white;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.small-cards-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
@ -647,12 +722,35 @@ color: white;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.small-card-cover {
|
||||
width: 100%;
|
||||
height: 163px;
|
||||
background: #1D1C2E;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.small-card-cover img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.small-card-cover video.preview-video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.small-card-info {
|
||||
@ -684,6 +782,7 @@ color: white;
|
||||
font-size: 14px;
|
||||
color: $light-violet;
|
||||
}
|
||||
|
||||
.pc-card {
|
||||
width: 233px;
|
||||
height: 164px;
|
||||
@ -724,7 +823,7 @@ color: white;
|
||||
font-size: 14px;
|
||||
line-height: 100%;
|
||||
letter-spacing: 0%;
|
||||
color: #3C3882;
|
||||
color: $violet;
|
||||
text-align: right;
|
||||
position: relative;
|
||||
right: 5px;
|
||||
@ -794,7 +893,7 @@ color: white;
|
||||
width: 276px;
|
||||
height: 40px;
|
||||
border-radius: 10px;
|
||||
background-color: #3C3882;
|
||||
background-color: $violet;
|
||||
color: white;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
@ -813,6 +912,9 @@ color: white;
|
||||
letter-spacing: 0%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* pagination */
|
||||
|
||||
.pagination-container {
|
||||
width: 626px;
|
||||
height: 50px;
|
||||
|
8
static/js/adjustScrollbar.js
Normal file
8
static/js/adjustScrollbar.js
Normal file
@ -0,0 +1,8 @@
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
||||
|
||||
document.body.style.paddingRight = `${scrollbarWidth}px`;
|
||||
|
||||
const navbarHeight = document.querySelector('.navbar').offsetHeight;
|
||||
document.documentElement.style.scrollPaddingTop = `${navbarHeight}px`;
|
||||
});
|
64
static/js/hoverPreview.js
Normal file
64
static/js/hoverPreview.js
Normal file
@ -0,0 +1,64 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const cardCovers = document.querySelectorAll('.small-card-cover, .card-cover');
|
||||
|
||||
cardCovers.forEach(cardCover => {
|
||||
const thumbnail = cardCover.querySelector('.thumbnail');
|
||||
const video = cardCover.querySelector('.preview-video');
|
||||
const videoSource = video.querySelector('source');
|
||||
let hoverTimeout;
|
||||
|
||||
cardCover.addEventListener('mouseenter', () => {
|
||||
hoverTimeout = setTimeout(() => {
|
||||
|
||||
if (!videoSource.src) {
|
||||
videoSource.src = video.dataset.src;
|
||||
video.load();
|
||||
}
|
||||
|
||||
thumbnail.style.display = 'none';
|
||||
video.style.display = 'block';
|
||||
|
||||
video.addEventListener('loadedmetadata', () => {
|
||||
|
||||
if (video.duration > 15) {
|
||||
|
||||
video.currentTime = 10;
|
||||
const loopSegment = () => {
|
||||
if (video.currentTime >= 15) {
|
||||
video.currentTime = 10;
|
||||
video.play();
|
||||
}
|
||||
};
|
||||
video.addEventListener('timeupdate', loopSegment);
|
||||
cardCover.loopSegment = loopSegment;
|
||||
} else {
|
||||
|
||||
video.currentTime = 0;
|
||||
const loopEntireVideo = () => {
|
||||
if (video.currentTime >= video.duration) {
|
||||
video.currentTime = 0;
|
||||
video.play();
|
||||
}
|
||||
};
|
||||
video.addEventListener('timeupdate', loopEntireVideo);
|
||||
cardCover.loopSegment = loopEntireVideo;
|
||||
}
|
||||
|
||||
video.play();
|
||||
});
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
cardCover.addEventListener('mouseleave', () => {
|
||||
clearTimeout(hoverTimeout);
|
||||
video.pause();
|
||||
video.style.display = 'none';
|
||||
thumbnail.style.display = 'block';
|
||||
|
||||
if (cardCover.loopSegment) {
|
||||
video.removeEventListener('timeupdate', cardCover.loopSegment);
|
||||
delete cardCover.loopSegment;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Navbar</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
@ -46,7 +45,7 @@
|
||||
<img src="{{ url_for('static', filename='navbar/discord-hover.svg') }}" alt="Discord Hover"
|
||||
class="discord-hover-icon">
|
||||
</div>
|
||||
<button class="login-btn">ВОЙТИ</button>
|
||||
<a href="{{ url_for('auth.login') }}"><button class="login-btn">ВОЙТИ</button></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Subnav</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
|
@ -5,7 +5,6 @@
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Tags List</title>
|
||||
<body>
|
||||
<div class="tags-container">
|
||||
{% for tag in tags %}
|
||||
|
@ -10,24 +10,30 @@
|
||||
<div class="container new-content">
|
||||
<a class="new-content-text">НОВИНКИ</a>
|
||||
<div class="small-cards-grid">
|
||||
{% for i in range(5) %}
|
||||
{% for video_data in videos[:5] %}
|
||||
<div class="small-card">
|
||||
<div class="small-card-cover"></div>
|
||||
<div class="small-card-cover">
|
||||
<img src="{{ url_for('static', filename='thumbnails/' + video_data.video.video_thumbnail_file) }}" alt="Thumbnail" class="thumbnail">
|
||||
<video class="preview-video" muted preload="none" data-src="{{ url_for('static', filename='videos/' + video_data.video.video_file) }}">
|
||||
<source type="video/mp4">
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
</div>
|
||||
<div class="small-card-info">
|
||||
<div class="small-card-header">
|
||||
<span class="small-card-text">Totoka</span>
|
||||
<span class="small-card-text">{{ video_data.video.username }}</span>
|
||||
<div class="small-card-stats">
|
||||
<div class="small-stat">
|
||||
<img src="{{ url_for('static', filename='card/like-icon.svg') }}" alt="Лайк" width="20" height="20">
|
||||
<span class="small-card-text">134</span>
|
||||
<span class="small-card-text">{{ video_data.video.cookie_votes }}</span>
|
||||
</div>
|
||||
<div class="small-stat">
|
||||
<img src="{{ url_for('static', filename='card/views-icon.svg') }}" alt="Просмотры" width="20" height="20">
|
||||
<span class="small-card-text">32113</span>
|
||||
<span class="small-card-text">{{ video_data.views_count }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="small-card-text">Big Brother Keep Hugging Me 4</p>
|
||||
<p class="small-card-text">{{ video_data.video.video_name }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
@ -37,51 +43,64 @@
|
||||
<div class="container popular-content">
|
||||
<a class="popular-content-text">ПОПУЛЯРНОЕ</a>
|
||||
<div class="cards-grid">
|
||||
{% for i in range(8) %}
|
||||
{% for video_data in popular_videos[:8] %}
|
||||
<div class="card">
|
||||
<div class="card-cover"></div>
|
||||
<div class="card-cover">
|
||||
<img src="{{ url_for('static', filename='thumbnails/' + video_data.video.video_thumbnail_file) }}" alt="Thumbnail" class="thumbnail">
|
||||
<video class="preview-video" muted preload="none" data-src="{{ url_for('static', filename='videos/' + video_data.video.video_file) }}">
|
||||
<source type="video/mp4">
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
</div>
|
||||
<div class="card-info">
|
||||
<div class="card-header">
|
||||
<span class="card-title" style="color: #3C3882;">Totoka</span>
|
||||
<span class="card-title" style="color: #3C3882;">{{ video_data.video.username }}</span>
|
||||
<div class="card-stats">
|
||||
<div class="stat">
|
||||
<img src="{{ url_for('static', filename='card/like-icon.svg') }}" alt="Лайк" width="20" height="20">
|
||||
<span style="color: #8784C9;">134</span>
|
||||
<span style="color: #8784C9;">{{ video_data.video.cookie_votes }}</span>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<img src="{{ url_for('static', filename='card/views-icon.svg') }}" alt="Просмотры" width="20" height="20">
|
||||
<span style="color: #8784C9;">32113</span>
|
||||
<span style="color: #8784C9;">{{ video_data.views_count }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="card-text" style="font-family: Nunito, sans-serif;">Big Brother Keep Hugging Me 4</p>
|
||||
<p class="card-text" style="font-family: Nunito, sans-serif;">{{ video_data.video.video_name }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<button class="view-more-button"><span class="new-context-button-text">Смотреть Больше</span></button>
|
||||
</div>
|
||||
|
||||
<div class="container viewed-content">
|
||||
<a class="viewed-content-text">ПРОСМАТРИВАЕМОЕ</a>
|
||||
<div class="cards-grid">
|
||||
{% for i in range(8) %}
|
||||
{% for video_data in most_viewed_videos[:8] %}
|
||||
<div class="card">
|
||||
<div class="card-cover"></div>
|
||||
<div class="card-cover">
|
||||
<img src="{{ url_for('static', filename='thumbnails/' + video_data.video.video_thumbnail_file) }}" alt="Thumbnail" class="thumbnail">
|
||||
<video class="preview-video" muted preload="none" data-src="{{ url_for('static', filename='videos/' + video_data.video.video_file) }}">
|
||||
<source type="video/mp4">
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
</div>
|
||||
<div class="card-info">
|
||||
<div class="card-header">
|
||||
<span class="card-title" style="color: #3C3882;">Totoka</span>
|
||||
<span class="card-title" style="color: #3C3882;">{{ video_data.video.username }}</span>
|
||||
<div class="card-stats">
|
||||
<div class="stat">
|
||||
<img src="{{ url_for('static', filename='card/like-icon.svg') }}" alt="Лайк" width="20" height="20">
|
||||
<span style="color: #8784C9;">134</span>
|
||||
<span style="color: #8784C9;">{{ video_data.video.cookie_votes }}</span>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<img src="{{ url_for('static', filename='card/views-icon.svg') }}" alt="Просмотры" width="20" height="20">
|
||||
<span style="color: #8784C9;">32113</span>
|
||||
<span style="color: #8784C9;">{{ video_data.views_count }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="card-text" style="font-family: Nunito, sans-serif;">Big Brother Keep Hugging Me 4</p>
|
||||
<p class="card-text" style="font-family: Nunito, sans-serif;">{{ video_data.video.video_name }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
@ -104,5 +123,7 @@
|
||||
{% endfor %}
|
||||
<button class="view-more-button"><span class="new-context-button-text">Смотреть Больше</span></button>
|
||||
</div>
|
||||
<script src="{{ url_for('static', filename='js/hoverPreview.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/adjustScrollbar.js') }}"></script>
|
||||
</body>
|
||||
</html>
|
Loading…
x
Reference in New Issue
Block a user