diff --git a/components/actors/tile.vue b/components/actors/tile.vue
index bf8e603..6b6248c 100644
--- a/components/actors/tile.vue
+++ b/components/actors/tile.vue
@@ -66,7 +66,16 @@
- {{ actor.name }}
+
+ {{ actor.name }}
+
+
+
@@ -119,9 +128,11 @@ const favorited = ref(props.actor.stashes.some((actorStash) => actorStash.id ===
}
}
-.name {
+.label {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
flex-shrink: 0;
- padding: .35rem .5rem;
font-weight: bold;
font-size: .9rem;
white-space: nowrap;
@@ -130,6 +141,15 @@ const favorited = ref(props.actor.stashes.some((actorStash) => actorStash.id ===
user-select: all;
}
+.name {
+ padding: .35rem .25rem .35rem .5rem;
+}
+
+.favicon {
+ height: 1rem;
+ padding: .35rem .5rem .35rem .25rem;
+}
+
.avatar-container {
position: relative;
flex-grow: 1;
diff --git a/pages/actors/@actorId/edit/+Page.vue b/pages/actors/@actorId/edit/+Page.vue
index b998452..dbe2be2 100644
--- a/pages/actors/@actorId/edit/+Page.vue
+++ b/pages/actors/@actorId/edit/+Page.vue
@@ -68,7 +68,7 @@
-
City
-
-
@@ -560,27 +584,53 @@
Penis length
-
+
+ cm
+
+
+
+ inch
+
Penis girth
-
+
+ cm
+
+
+
+ inch
+
@@ -690,7 +740,7 @@ const user = pageContext.user;
const countries = pageContext.pageProps.countries;
const actor = ref(pageContext.pageProps.actor);
-console.log(actor.value);
+// console.log(actor.value);
const topCountries = [
'AU',
@@ -705,26 +755,6 @@ const topCountries = [
const sortedCountries = countries.toSorted((countryA, countryB) => topCountries.indexOf(countryB.alpha2) - topCountries.indexOf(countryA.alpha2));
-/*
-const cupSizes = [
- 'A', 'AA',
- 'B',
- 'C',
- 'D', 'DD', 'DDD',
- 'E',
- 'F', 'FF',
- 'G', 'GG',
- 'H', 'HH',
- 'J', 'JJ',
- 'K', 'KK',
- 'L',
- 'M',
- 'N',
- 'O',
- 'P',
-];
-*/
-
const cupSizes = {
us: ['AA', 'A', 'B', 'C', 'D', ['DD', 'E'], ['DDD', 'F'], 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'], // United States
uk: ['AA', 'A', 'B', 'C', 'D', 'DD', 'E', 'F', 'FF', 'G', 'GG', 'H', 'HH', 'J', 'JJ', 'K', 'KK'], // United Kingdom
@@ -778,28 +808,42 @@ const fields = computed(() => [
: null,
inline: true,
},
+ {
+ key: 'ethnicity',
+ type: 'string',
+ value: actor.value.ethnicity,
+ suggestions: [
+ 'Asian',
+ 'Black',
+ 'Indian',
+ 'Latina',
+ 'White',
+ ],
+ },
{
key: 'origin',
type: 'place',
value: {
- ...actor.value.origin,
country: actor.value.origin?.country?.alpha2 || null,
+ place: [actor.value.origin?.city, actor.value.origin?.state].filter(Boolean).join(', '),
},
},
{
key: 'residence',
type: 'place',
value: {
- ...actor.value.residence,
country: actor.value.residence?.country?.alpha2 || null,
+ place: [actor.value.residence?.city, actor.value.residence?.state].filter(Boolean).join(', '),
},
},
{
key: 'size',
type: 'size',
value: {
- height: actor.value.height?.metric,
- weight: actor.value.weight?.metric,
+ metricHeight: actor.value.height?.metric,
+ metricWeight: actor.value.weight?.metric,
+ imperialHeight: actor.value.height?.imperial || [],
+ imperialWeight: actor.value.weight?.imperial,
},
},
{
@@ -900,8 +944,10 @@ const fields = computed(() => [
key: 'penis',
type: 'penis',
value: {
- penisLength: actor.value.penisLength?.imperial,
- penisGirth: actor.value.penisGirth?.imperial,
+ metricLength: actor.value.penisLength?.metric,
+ metricGirth: actor.value.penisGirth?.metric,
+ imperialLength: actor.value.penisLength?.imperial,
+ imperialGirth: actor.value.penisGirth?.imperial,
isCircumcised: actor.value.isCircumcised,
},
},
@@ -943,27 +989,49 @@ function setAvatar(avatarId) {
const keyMap = {
origin: {
country: 'originCountry',
- state: 'originState',
- city: 'originCity',
+ place: 'originPlace',
},
residence: {
country: 'residenceCountry',
- state: 'residenceState',
- city: 'residenceCity',
+ place: 'residencePlace',
},
};
+const groupMap = {
+ penisLength: 'penis',
+ penisGirth: 'penis',
+ height: 'size',
+ weight: 'size',
+};
+
async function submit() {
try {
await post('/revisions/actors', {
actorId: actor.value.id,
- edits: Object.fromEntries(Array.from(editing.value).flatMap((key) => {
- if (edits.value[key] && typeof edits.value[key] === 'object') {
- return Object.entries(edits.value[key]).map(([valueKey, value]) => [keyMap[key]?.[valueKey] || valueKey, value]);
- }
+ edits: {
+ ...Object.fromEntries(Array.from(editing.value).flatMap((key) => {
+ if (edits.value[key] && typeof edits.value[key] === 'object') {
+ return Object.entries(edits.value[key]).map(([valueKey, value]) => [keyMap[key]?.[valueKey] || valueKey, value]);
+ }
- return [[key, edits.value[key]]];
- })),
+ return [[key, edits.value[key]]];
+ })),
+ ...Object.fromEntries(Object.entries({
+ height: sizeUnits.value === 'imperial' ? edits.value.size.imperialHeight : edits.value.size.metricHeight,
+ weight: sizeUnits.value === 'imperial' ? edits.value.size.imperialWeight : edits.value.size.metricWeight,
+ penisLength: penisUnits.value === 'imperial' ? edits.value.penis.imperialLength : edits.value.penis.metricLength,
+ penisGirth: penisUnits.value === 'imperial' ? edits.value.penis.imperialGirth : edits.value.penis.metricGirth,
+ }).filter(([key]) => editing.value.has(groupMap[key] || key))),
+ metricHeight: undefined,
+ metricWeight: undefined,
+ imperialHeight: undefined,
+ imperialWeight: undefined,
+ metricLength: undefined,
+ metricGirth: undefined,
+ imperialLength: undefined,
+ imperialGirth: undefined,
+ },
+ sizeUnits: sizeUnits.value,
figureUnits: figureUnits.value,
penisUnits: penisUnits.value,
comment: comment.value,
diff --git a/src/actors.js b/src/actors.js
index 4c8afe9..4373bd7 100644
--- a/src/actors.js
+++ b/src/actors.js
@@ -59,6 +59,12 @@ export function curateActor(actor, context = {}) {
name: actor.name,
gender: actor.gender,
age: actor.age,
+ ethnicity: actor.ethnicity,
+ entity: actor.entity && {
+ id: actor.entity.id,
+ slug: actor.entity.slug,
+ name: actor.entity.name,
+ },
...Object.fromEntries(Object.entries(keyMap).map(([key, entryKey]) => [key, actor[entryKey]])),
ageFromBirth: actor.date_of_birth && differenceInYears(Date.now(), actor.date_of_birth),
ageThen: context.sceneDate && actor.date_of_birth && differenceInYears(context.sceneDate, actor.date_of_birth),
@@ -166,11 +172,13 @@ export async function fetchActorsById(actorIds, options = {}, reqUser) {
knex.raw('COALESCE(birth_countries.alias, birth_countries.name) as birth_country_name'),
'residence_countries.alpha2 as residence_country_alpha2',
knex.raw('COALESCE(residence_countries.alias, residence_countries.name) as residence_country_name'),
+ knex.raw('row_to_json(entities) as entity'),
)
.leftJoin('actors_meta', 'actors_meta.actor_id', 'actors.id')
.leftJoin('countries as birth_countries', 'birth_countries.alpha2', 'actors.birth_country_alpha2')
.leftJoin('countries as residence_countries', 'residence_countries.alpha2', 'actors.residence_country_alpha2')
.leftJoin('media as avatars', 'avatars.id', 'actors.avatar_media_id')
+ .leftJoin('entities', 'entities.id', 'actors.entity_id')
.whereIn('actors.id', actorIds)
.modify((builder) => {
if (options.order) {
@@ -199,8 +207,8 @@ export async function fetchActorsById(actorIds, options = {}, reqUser) {
)
.whereIn('actor_id', actorIds)
.leftJoin('media', 'media.id', 'actors_avatars.media_id')
- .groupBy('media.id', 'actors_avatars.actor_id', 'actors_avatars.created_at')
- .orderBy('actors_avatars.created_at', 'desc'),
+ .groupBy('media.id', 'actors_avatars.actor_id')
+ .orderBy(knex.raw('max(actors_avatars.created_at)'), 'desc'),
reqUser
? knex('stashes_actors')
.leftJoin('stashes', 'stashes.id', 'stashes_actors.stash_id')
@@ -549,34 +557,6 @@ async function fetchMainProfile(actorId, wasCreated = false) {
return fetchMainProfile(actorId, true);
}
-/*
-async function applyMainProfile(actorId) {
- const [actorEntry, mainProfile] = await Promise.all([
- knex('actors')
- .where('id', actorId)
- .first(),
- fetchMainProfile(actorId),
- ]);
-
- if (!actorEntry) {
- throw new HttpError('No actor profile found to apply main profile to', 404);
- }
-
- const preservedKeys = ['id'];
-
- // we start iterating from the actor entry so we don't include keys that are not yet supported by the actors table
- const mergedProfile = Object.fromEntries(Object.entries(actorEntry)
- .filter(([key]) => Object.hasOwn(mainProfile, key))
- .map(([key, value]) => [key, mainProfile[key] === null || preservedKeys.includes(key)
- ? value
- : mainProfile[key]]));
-
- await knex('actors')
- .where('id', actorId)
- .update(mergedProfile);
-}
-*/
-
async function applyActorRevision(revisionIds, reqUser) {
const revisions = await knex('actors_revisions')
.whereIn('id', revisionIds)
@@ -600,6 +580,7 @@ async function applyActorRevision(revisionIds, reqUser) {
'residenceCountry',
'residenceState',
'residenceCity',
+ 'ethnicity',
'height',
'weight',
'bust',
@@ -755,6 +736,27 @@ function convertFigure(domain = 'cup', rawValue, units) {
return usValue;
}
+function convertHeight(height, units) {
+ if (units === 'metric' || !Array.isArray(height)) {
+ return Number(height) || null;
+ }
+
+ if (height.length !== 2) {
+ return null;
+ }
+
+ // 12 inches in a foot
+ return Math.round(((height[0] * 12) + height[1]) * 2.54);
+}
+
+function convertWeight(weight, units) {
+ if (units === 'imperial') {
+ return Math.round(unit(weight, 'lbs').toNumeric('kg'));
+ }
+
+ return Number(weight) || null;
+}
+
export async function createActorRevision(actorId, {
edits,
comment,
@@ -819,15 +821,9 @@ export async function createActorRevision(actorId, {
return null;
}
- if (Array.isArray(value)) {
- const valueSet = new Set(value);
- const baseSet = new Set(baseActor[key]);
-
- if (valueSet.size === baseSet.size && baseActor[key].every((id) => valueSet.has(id))) {
- return null;
- }
-
- return { key, value: Array.from(valueSet) };
+ if (['originPlace', 'residencePlay'].includes(key)) {
+ console.log(key, value);
+ throw new Error('must be converted first!');
}
if (['cup', 'bust', 'waist', 'hip'].includes(key)) {
@@ -844,9 +840,49 @@ export async function createActorRevision(actorId, {
};
}
+ if (['height'].includes(key)) {
+ const convertedValue = convertHeight(value, options.sizeUnits);
+
+ if (baseActor[key] === convertedValue) {
+ return null;
+ }
+
+ const conversionComment = !value || convertedValue === value
+ ? null
+ : `${key} converted from ${value[0]} in ${value[1]} ft to ${convertedValue} cm`;
+
+ return {
+ key,
+ value: convertedValue,
+ comment: conversionComment,
+ };
+ }
+
+ if (['weight'].includes(key)) {
+ const convertedValue = convertWeight(value, options.sizeUnits);
+
+ if (baseActor[key] === convertedValue) {
+ return null;
+ }
+
+ const conversionComment = !value || convertedValue === value
+ ? null
+ : `${key} converted from ${value} lbs to ${convertedValue} kg`;
+
+ return {
+ key,
+ value: convertedValue,
+ comment: conversionComment,
+ };
+ }
+
if (['penisLength', 'penisGirth'].includes(key) && options.penisUnits === 'imperial') {
const convertedValue = Math.round(convert(value, 'inches').to('cm'));
+ if (baseActor[key] === convertedValue) {
+ return null;
+ }
+
return {
key,
value: convertedValue,
@@ -854,6 +890,17 @@ export async function createActorRevision(actorId, {
};
}
+ if (Array.isArray(value)) {
+ const valueSet = new Set(value);
+ const baseSet = new Set(baseActor[key]);
+
+ if (valueSet.size === baseSet.size && baseActor[key].every((id) => valueSet.has(id))) {
+ return null;
+ }
+
+ return { key, value: Array.from(valueSet) };
+ }
+
return { key, value };
}).filter(Boolean);