Ad UI cleanup

This commit is contained in:
Mr. Stallion 2020-03-22 13:39:45 -05:00
parent a95d483eb6
commit 2466e8f3be
7 changed files with 207 additions and 98 deletions

View File

@ -0,0 +1,96 @@
<template>
<modal :action="`Ad settings for ${conversation.name}`" @submit="submit" ref="dialog" @open="load()" dialogClass="w-100"
:buttonText="l('conversationSettings.save')">
<div class="form-group ad-list" v-for="(ad, index) in ads">
<label :for="'ad' + conversation.key + '-' + index" class="control-label">Ad #{{(index + 1)}}
<a v-if="(index > 0)" @click="moveAdUp(index)" title="Move Up"><i class="fa fa-arrow-up"></i></a>
<a v-if="(index < ads.length - 1)" @click="moveAdDown(index)" title="Move Down"><i class="fa fa-arrow-down"></i></a>
<a @click="removeAd(index)" title="Remove Ad"><i class="fa fa-minus-circle"></i></a>
</label>
<textarea :id="'ad' + conversation.key + '-' + index" class="form-control" v-model="ads[index]"></textarea>
</div>
<button class="btn btn-outline-secondary" @click="addAd()">Add Another</button>
</modal>
</template>
<script lang="ts">
import {Component, Prop} from '@f-list/vue-ts';
import CustomDialog from '../components/custom_dialog';
import Modal from '../components/Modal.vue';
import {Conversation} from './interfaces';
import l from './localize';
@Component({
components: {modal: Modal}
})
export default class ConversationAdSettings extends CustomDialog {
@Prop({required: true})
readonly conversation!: Conversation;
l = l;
setting = Conversation.Setting;
ads!: string[];
load(): void {
const settings = this.conversation.settings;
this.ads = settings.adSettings.ads.slice(0);
if (this.ads.length === 0) {
this.ads.push('');
}
}
submit(): void {
this.conversation.settings = {
notify: this.conversation.settings.notify,
highlight: this.conversation.settings.highlight,
highlightWords: this.conversation.settings.highlightWords,
joinMessages: this.conversation.settings.joinMessages,
defaultHighlights: this.conversation.settings.defaultHighlights,
adSettings: {
ads: this.ads.map((ad: string) => ad.trim()).filter((ad: string) => (ad.length > 0))
}
};
}
addAd(): void {
this.ads.push('');
}
removeAd(index: number): void {
if (confirm('Are you sure you wish to remove this ad?')) {
this.ads.splice(index, 1);
}
}
moveAdUp(index: number): void {
const ad = this.ads.splice(index, 1);
this.ads.splice(index - 1, 0, ad[0]);
}
moveAdDown(index: number): void {
const ad = this.ads.splice(index, 1);
this.ads.splice(index + 1, 0, ad[0]);
}
}
</script>
<style lang="scss">
.form-group.ad-list label a {
padding-right: 0.3rem;
opacity:0.3
}
.form-group.ad-list label a:hover {
opacity:0.6
}
</style>

View File

@ -35,19 +35,6 @@
<option :value="setting.False">{{l('conversationSettings.false')}}</option>
</select>
</div>
<h5>Auto-Posting Channel Ads</h5>
<div class="form-group ad-list" v-for="(ad, index) in ads">
<label :for="'ad' + conversation.key + '-' + index" class="control-label">Ad #{{(index + 1)}}
<a v-if="(index > 0)" @click="moveAdUp(index)" title="Move Up"><i class="fa fa-arrow-up"></i></a>
<a v-if="(index < ads.length - 1)" @click="moveAdDown(index)" title="Move Down"><i class="fa fa-arrow-down"></i></a>
<a @click="removeAd(index)" title="Remove Ad"><i class="fa fa-minus-circle"></i></a>
</label>
<textarea :id="'ad' + conversation.key + '-' + index" class="form-control" v-model="ads[index]"></textarea>
</div>
<button class="btn btn-outline-secondary" @click="addAd()">Add Another</button>
</modal>
</template>
@ -71,7 +58,6 @@
highlightWords!: string;
joinMessages!: Conversation.Setting;
defaultHighlights!: boolean;
ads!: string[];
load(): void {
const settings = this.conversation.settings;
@ -80,11 +66,6 @@
this.highlightWords = settings.highlightWords.join(',');
this.joinMessages = settings.joinMessages;
this.defaultHighlights = settings.defaultHighlights;
this.ads = settings.adSettings.ads.slice(0);
if (this.ads.length === 0) {
this.ads.push('');
}
}
submit(): void {
@ -94,49 +75,9 @@
highlightWords: this.highlightWords.split(',').map((x) => x.trim()).filter((x) => (x.length > 0)),
joinMessages: this.joinMessages,
defaultHighlights: this.defaultHighlights,
adSettings: {
ads: this.ads.map((ad: string) => ad.trim()).filter((ad: string) => (ad.length > 0))
}
adSettings: this.conversation.settings.adSettings
};
}
addAd(): void {
this.ads.push('');
}
removeAd(index: number): void {
if (confirm('Are you sure you wish to remove this ad?')) {
this.ads.splice(index, 1);
}
}
moveAdUp(index: number): void {
const ad = this.ads.splice(index, 1);
this.ads.splice(index - 1, 0, ad[0]);
}
moveAdDown(index: number): void {
const ad = this.ads.splice(index, 1);
this.ads.splice(index + 1, 0, ad[0]);
}
}
</script>
<style lang="scss">
.form-group.ad-list label a {
padding-right: 0.3rem;
opacity:0.3
}
.form-group.ad-list label a:hover {
opacity:0.6
}
</style>

View File

@ -50,16 +50,31 @@
<a href="#" @click.prevent="reportDialog.report()" class="btn">
<span class="fa fa-exclamation-triangle"></span><span class="btn-text">{{l('chat.report')}}</span></a>
</div>
<ul class="nav nav-pills mode-switcher">
<li v-for="mode in modes" class="nav-item">
<a :class="isChannel(conversation) ? {active: conversation.mode == mode, disabled: conversation.channel.mode != 'both'} : undefined"
class="nav-link" href="#" @click.prevent="setMode(mode)">{{l('channel.mode.' + mode)}}</a>
</li>
<li>
<a @click.prevent="toggleNonMatchingAds()" :class="{active: showNonMatchingAds}" v-show="(conversation.mode == 'both' || conversation.mode == 'ads')"
class="nav-link" href="#">Non-Matching</a>
</li>
</ul>
<!-- <ul class="nav nav-pills mode-switcher">-->
<!-- <li v-for="mode in modes" class="nav-item">-->
<!-- <a :class="isChannel(conversation) ? {active: conversation.mode == mode, disabled: conversation.channel.mode != 'both'} : undefined"-->
<!-- class="nav-link" href="#" @click.prevent="setMode(mode)">{{l('channel.mode.' + mode)}}</a>-->
<!-- </li>-->
<!-- <li>-->
<!-- <a @click.prevent="toggleNonMatchingAds()" :class="{active: showNonMatchingAds}" v-show="(conversation.mode == 'both' || conversation.mode == 'ads')"-->
<!-- class="nav-link" href="#">Non-Matching</a>-->
<!-- </li>-->
<!-- </ul>-->
<div class="btn-toolbar">
<dropdown :keep-open="false" title="View" :icon-class="{fas: true, 'fa-comments': conversation.mode === 'chat', 'fa-ad': conversation.mode === 'ads', 'fa-asterisk': conversation.mode === 'both'}" wrap-class="btn-group views" link-class="btn btn-secondary dropdown-toggle" v-show="(conversation.channel.mode == 'both')">
<button v-for="mode in modes" class="dropdown-item" :class="{ selected: conversation.mode == mode }" type="button" @click="setMode(mode)">{{l('channel.mode.' + mode)}}</button>
</dropdown>
<dropdown :keep-open="false" title="Ads" :icon-class="{fas: true, 'fa-pause': !conversation.adManager.isActive(), 'fa-play': conversation.adManager.isActive()}" wrap-class="btn-group ads" link-class="btn btn-secondary dropdown-toggle" v-show="(conversation.channel.mode == 'both' || conversation.channel.mode == 'ads')">
<button class="dropdown-item" type="button" @click="toggleAutoPostAds()">{{conversation.adManager.isActive() ? 'Stop' : 'Start'}} Posting Ads</button>
<button class="dropdown-item" type="button" @click="showAdSettings()">Edit Channel Ads</button>
<div class="dropdown-divider"></div>
<button class="dropdown-item" :class="{ selected: showNonMatchingAds }" type="button" @click="toggleNonMatchingAds()">Show Incompatible Ads</button>
</dropdown>
</div>
</div>
<div style="z-index:5;position:absolute;left:0;right:0;max-height:60%;overflow:auto"
:style="{display: descriptionExpanded ? 'block' : 'none'}" class="bg-solid-text border-bottom">
@ -91,7 +106,7 @@
</div>
<a class="btn btn-sm btn-outline-primary renew-autoposts" @click="renewAutoPosting()" v-if="!adsRequireSetup">{{l('admgr.renew')}}</a>
<a class="btn btn-sm btn-outline-primary renew-autoposts" @click="showSettings()" v-if="adsRequireSetup">{{l('admgr.setup')}}</a>
<a class="btn btn-sm btn-outline-primary renew-autoposts" @click="showAdSettings()" v-if="adsRequireSetup">{{l('admgr.setup')}}</a>
</div>
<div class="border-top messages" :class="getMessageWrapperClasses()" ref="messages"
@scroll="onMessagesScroll" style="flex:1;overflow:auto;margin-top:2px">
@ -130,23 +145,24 @@
</div>
<ul class="nav nav-pills send-ads-switcher" v-if="isChannel(conversation)"
style="position:relative;z-index:10;margin-right:5px">
<li class="nav-item">
<li class="nav-item" v-show="((conversation.channel.mode === 'both') || (conversation.channel.mode === 'chat'))">
<a href="#" :class="{active: !conversation.isSendingAds, disabled: (conversation.channel.mode != 'both') || (conversation.adManager.isActive())}"
class="nav-link" @click.prevent="setSendingAds(false)">{{l('channel.mode.chat')}}</a>
</li>
<li class="nav-item">
<li class="nav-item" v-show="((conversation.channel.mode === 'both') || (conversation.channel.mode === 'ads'))">
<a href="#" :class="{active: conversation.isSendingAds, disabled: (conversation.channel.mode != 'both') || (conversation.adManager.isActive())}"
class="nav-link" @click.prevent="setSendingAds(true)">{{adsMode}}</a>
</li>
<li class="nav-item">
<a href="#" :class="{active: conversation.adManager.isActive()}" class="nav-link toggle-autopost" @click="toggleAutoPostAds()">{{l('admgr.toggleAutoPost')}}</a>
</li>
<!-- <li class="nav-item">-->
<!-- <a href="#" :class="{active: conversation.adManager.isActive()}" class="nav-link toggle-autopost" @click="toggleAutoPostAds()">{{l('admgr.toggleAutoPost')}}</a>-->
<!-- </li>-->
</ul>
<div class="btn btn-sm btn-primary" v-show="!settings.enterSend" @click="sendButton">{{l('chat.send')}}</div>
</div>
</bbcode-editor>
<command-help ref="helpDialog"></command-help>
<settings ref="settingsDialog" :conversation="conversation"></settings>
<adSettings ref="adSettingsDialog" :conversation="conversation"></adSettings>
<logs ref="logsDialog" :conversation="conversation"></logs>
<manage-channel ref="manageDialog" v-if="isChannel(conversation)" :channel="conversation.channel"></manage-channel>
<ad-view ref="adViewer" v-if="isPrivate(conversation) && conversation.character" :character="conversation.character"></ad-view>
@ -166,6 +182,7 @@
import CommandHelp from './CommandHelp.vue';
import { characterImage, getByteLength, getKey } from './common';
import ConversationSettings from './ConversationSettings.vue';
import ConversationAdSettings from './ConversationAdSettings.vue';
import core from './core';
import {Channel, channelModes, Character, Conversation, Settings} from './interfaces';
import l from './localize';
@ -177,13 +194,14 @@
import UserView from './UserView.vue';
import UserChannelList from './UserChannelList.vue';
import * as _ from 'lodash';
import Dropdown from '../components/Dropdown.vue';
@Component({
components: {
user: UserView, 'bbcode-editor': Editor, 'manage-channel': ManageChannel, settings: ConversationSettings,
logs: Logs, 'message-view': MessageView, bbcode: BBCodeView(core.bbCodeParser), 'command-help': CommandHelp,
'ad-view': AdView, 'channel-list': UserChannelList
'ad-view': AdView, 'channel-list': UserChannelList, dropdown: Dropdown, adSettings: ConversationAdSettings
}
})
export default class ConversationView extends Vue {
@ -447,6 +465,10 @@
(<ConversationSettings>this.$refs['settingsDialog']).show();
}
showAdSettings(): void {
(<ConversationAdSettings>this.$refs['adSettingsDialog']).show();
}
showManage(): void {
(<ManageChannel>this.$refs['manageDialog']).show();
}
@ -573,6 +595,47 @@
}
}
.btn-toolbar {
.btn-group {
margin-right: 0.3rem;
&:last-child {
margin-right: 0;
}
a.btn {
padding-left: 0.5rem;
padding-right: 0.5rem;
i {
margin-right: 0.4rem;
font-size: 90%;
}
}
button::before {
display: inline-block;
width: 1.3rem;
height: 1rem;
content: '';
margin-left: -1.3rem;
margin-right: 0.1rem;
padding-left: 0.3rem;
font-weight: bold;
}
button.selected::before {
content: '✓';
}
&.views {
button.selected::before {
content: '•';
}
}
}
}
.send-ads-switcher a {
padding: 3px 10px;
}
@ -584,13 +647,14 @@
.auto-ads {
background-color: rgba(255, 128, 32, 0.8);
background-color: rgb(220, 113, 31);
padding-left: 10px;
padding-right: 10px;
padding-top: 5px;
padding-bottom: 5px;
margin: 0;
position: relative;
margin-top: 5px;
.renew-autoposts {
display: block;

View File

@ -21,14 +21,13 @@
<script lang="ts">
import { Component, Hook, Prop } from '@f-list/vue-ts';
import Modal from '../components/Modal.vue';
import Dropdown from '../components/Dropdown.vue';
import CustomDialog from '../components/custom_dialog';
import core from './core';
import { BBCodeView } from '../bbcode/view';
import * as _ from 'lodash';
@Component({
components: {modal: Modal, dropdown: Dropdown, bbcode: BBCodeView(core.bbCodeParser)}
components: {modal: Modal, bbcode: BBCodeView(core.bbCodeParser)}
})
export default class StatusPicker extends CustomDialog {
@Prop({required: true})

View File

@ -20,11 +20,11 @@ const strings: {[key: string]: string | undefined} = {
'admgr.postingBegins': 'Posting beings in {0}m {1}s',
'admgr.nextPostDue': 'Next ad in {0}m {1}s',
'admgr.expiresIn': ', auto-posting expires in {0}m {1}s',
'admgr.noAds': 'No ads have been set up -- auto-posting will be cancelled. Click "Tab Settings" to set up your ads.',
'admgr.noAds': 'No ads have been set up -- auto-posting will be cancelled. Click "Ads > Edit Channel Ads" to set up your ads.',
'admgr.activeHeader': 'Auto-Posting Ads',
'admgr.comingNext': 'Coming Next',
'admgr.renew': 'Renew',
'admgr.setup': 'Setup Ads',
'admgr.setup': 'Set-Up Ads',
'admgr.toggleAutoPost': 'Auto-Post Ads',
'consoleWarning.head': 'THIS IS THE DANGER ZONE.',
'consoleWarning.body': `ANYTHING YOU WRITE OR PASTE IN HERE COULD BE USED TO STEAL YOUR PASSWORDS OR TAKE OVER YOUR ENTIRE COMPUTER. This is where happiness goes to die. If you aren't a developer or a special kind of daredevil, please get out of here!`,
@ -439,4 +439,4 @@ export default function l(key: string, ...args: (string | number)[]): string {
while(i-- > 0)
str = str.replace(new RegExp(`\\{${i}\\}`, 'igm'), args[i].toString());
return str;
}
}

View File

@ -1,7 +1,8 @@
<template>
<div class="dropdown" @focusout="blur">
<div :class="wrapClass" @focusout="blur">
<a :class="linkClass" aria-haspopup="true" :aria-expanded="isOpen" @click.prevent="isOpen = !isOpen" href="#"
style="width:100%;text-align:left;align-items:center" role="button" tabindex="-1" ref="button">
<i :class="iconClass" v-if="!!iconClass"></i>
<slot name="title">{{title}}</slot>
</a>
<div class="dropdown-menu" ref="menu" @mousedown.prevent.stop @click.prevent.stop="menuClick()">
@ -19,6 +20,10 @@
isOpen = false;
@Prop({default: 'btn btn-secondary dropdown-toggle'})
readonly linkClass!: string;
@Prop({default: 'dropdown'})
readonly wrapClass!: string;
@Prop
readonly iconClass?: string;
@Prop
readonly keepOpen?: boolean;
@Prop
@ -52,4 +57,4 @@
if(!this.keepOpen) this.isOpen = false;
}
}
</script>
</script>

View File

@ -31,7 +31,7 @@ This repository contains a heavily customized version of the mainline F-Chat 3.0
* Custom kink explanations can be expanded inline
* Custom kinks are highlighted
* Gender, anthro/human preference, age, sexual preference, and sub/dom preference are highlighted if compatible or incompatible
* Guestbook, friend, and group counts are visible on tabs
* Guestbook, friend, and group counts are visible on tab titles
* Character images are expanded inline
* Cleaner presentation for the side bar details (age, etc.), sorted in most relevant order
* Less informative side bar details (views, contact) are separated and shown in a less prominent way
@ -55,17 +55,26 @@ This repository contains a heavily customized version of the mainline F-Chat 3.0
## How to Set Up Ads
1. Open a conversation channel of your preference, such as `#LFRP`
1. Click `Tab Settings`
1. Enter one or more `Channel Auto-Posting Ads`
1. Open a conversation channel of your preference, such as `#Sex Driven LFRP`
1. Locate `Ads` dropdown at the top right corner of the channel view
1. Click `Ads > Edit Channel Ads`
1. Enter one or more ads
1. Click `Save settings`
1. Click `Auto-Post Ads`
1. Click `Ads > Start Posting Ads`
1. To stop, click `Ads > Stop Posting Ads`
## FAQ
1. The more information you have in your profile (**non-custom** kinks in particular), the better the matching quality will be.
1. Non-binary gender preference matching relies on kinks. For example, if your non-binary character has a preference for females, make sure 'females' are listed as a favorite kink.
1. The more information you have in your profile (**non-custom** kinks in particular), the better the matching quality will be. The algorithm considers the following data points:
* Age
* Gender
* Sexual preference
* Dominance preference
* Human/anthro preference
* Non-custom kinks
* Species
1. Maching for non-binary genders relies on kinks. For example, if your non-binary character has a preference for females, make sure 'females' are listed as a favorite kink.
1. 'Underage' kink is considered to apply to characters aged 16 or above; 'ageplay' kink is considered to apply to characters aged 16 or below.
1. 'Older characters' and 'younger characters' kink preferences are interpreted as age difference of 5+ years.
1. Comparison results will get faster over time, as more and more character data is cached.
@ -75,15 +84,10 @@ This repository contains a heavily customized version of the mainline F-Chat 3.0
* Collect data on ads / responses to determine which ads work best
* Preview mode should allow detaching from the main window
* Split chat view / separate window for specific chats?
* Improve log browsing
* Reposition ad settings and toggle
* Save character's status messages
* Conversation bot API
* 'Filter unmatching ads' is not channel specific -- it's either on everywhere or nowhere
* AD UI Cleanup / hide to popovers?
* image loading animation
* Usually submissive vs usually submissive shows up as 'maybe'?
* Bug? Usually submissive vs usually submissive shows up as 'maybe'
# F-List Exported