add method for filtering
This commit is contained in:
@@ -70,150 +70,150 @@ export default class FileModel {
|
||||
const didStore: boolean = this.storeFileContent(fileContent);
|
||||
if (didStore == false) return;
|
||||
|
||||
switch (fileContent.type) {
|
||||
case "board-info":
|
||||
case "task":
|
||||
this.boardsAndTasksModel.handleFileContent(fileContent);
|
||||
break;
|
||||
case "reaction":
|
||||
this.chatModel.handleReaction(fileContent);
|
||||
break;
|
||||
}
|
||||
switch (fileContent.type) {
|
||||
case "board-info":
|
||||
case "task":
|
||||
this.boardsAndTasksModel.handleFileContent(fileContent);
|
||||
break;
|
||||
case "reaction":
|
||||
this.chatModel.handleReaction(fileContent);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
// methods
|
||||
readonly addFileContentAndSend = (
|
||||
fileContent: FileContent<string>,
|
||||
fileContent: FileContent<string>,
|
||||
): void => {
|
||||
this.handleFileContent(fileContent);
|
||||
this.chatModel.sendMessage("", undefined, fileContent);
|
||||
this.handleFileContent(fileContent);
|
||||
this.chatModel.sendMessage("", undefined, fileContent);
|
||||
};
|
||||
|
||||
// storage
|
||||
readonly storeFileContent = (fileContent: FileContent<string>): boolean => {
|
||||
const fileContentPath: string[] = this.getFileContentPath(
|
||||
fileContent.fileId,
|
||||
fileContent.fileContentId,
|
||||
);
|
||||
const fileContentPath: string[] = this.getFileContentPath(
|
||||
fileContent.fileId,
|
||||
fileContent.fileContentId,
|
||||
);
|
||||
|
||||
// check if fileContent already exists
|
||||
const existingFileContent: string | null =
|
||||
this.storageModel.read(fileContentPath);
|
||||
if (existingFileContent != null) return false;
|
||||
// check if fileContent already exists
|
||||
const existingFileContent: string | null =
|
||||
this.storageModel.read(fileContentPath);
|
||||
if (existingFileContent != null) return false;
|
||||
|
||||
const stringifiedContent: string = stringify(fileContent);
|
||||
this.storageModel.write(fileContentPath, stringifiedContent);
|
||||
return true;
|
||||
const stringifiedContent: string = stringify(fileContent);
|
||||
this.storageModel.write(fileContentPath, stringifiedContent);
|
||||
return true;
|
||||
};
|
||||
|
||||
readonly listFileIds = (): string[] => {
|
||||
return this.storageModel.list(this.basePath);
|
||||
return this.storageModel.list(this.basePath);
|
||||
};
|
||||
|
||||
readonly listFileContentIds = (fileId: string): string[] => {
|
||||
const filePath: string[] = this.getFilePath(fileId);
|
||||
return this.storageModel.list(filePath);
|
||||
const filePath: string[] = this.getFilePath(fileId);
|
||||
return this.storageModel.list(filePath);
|
||||
};
|
||||
|
||||
readonly selectLatestFileContentId = (
|
||||
fileContentIds: string[],
|
||||
fileContentIds: string[],
|
||||
): string | undefined => {
|
||||
return fileContentIds[fileContentIds.length - 1];
|
||||
return fileContentIds[fileContentIds.length - 1];
|
||||
};
|
||||
|
||||
readonly getFileContent = <T extends FileContent<string>>(
|
||||
fileId: string,
|
||||
fileContentName: string,
|
||||
reference: T,
|
||||
fileId: string,
|
||||
fileContentName: string,
|
||||
reference: T,
|
||||
): T | null => {
|
||||
const filePath: string[] = this.getFileContentPath(
|
||||
fileId,
|
||||
fileContentName,
|
||||
);
|
||||
const fileContentOrNull: T | null = this.storageModel.readStringifiable(
|
||||
filePath,
|
||||
reference,
|
||||
);
|
||||
return fileContentOrNull;
|
||||
const filePath: string[] = this.getFileContentPath(
|
||||
fileId,
|
||||
fileContentName,
|
||||
);
|
||||
const fileContentOrNull: T | null = this.storageModel.readStringifiable(
|
||||
filePath,
|
||||
reference,
|
||||
);
|
||||
return fileContentOrNull;
|
||||
};
|
||||
|
||||
readonly getLatestFileContent = <T extends FileContent<string>>(
|
||||
fileId: string,
|
||||
reference: T,
|
||||
fileId: string,
|
||||
reference: T,
|
||||
): T | null => {
|
||||
const fileContentsIds: string[] = this.listFileContentIds(fileId);
|
||||
const latestFileContentId: string | undefined =
|
||||
this.selectLatestFileContentId(fileContentsIds);
|
||||
if (latestFileContentId == undefined) return null;
|
||||
const fileContentsIds: string[] = this.listFileContentIds(fileId);
|
||||
const latestFileContentId: string | undefined =
|
||||
this.selectLatestFileContentId(fileContentsIds);
|
||||
if (latestFileContentId == undefined) return null;
|
||||
|
||||
const fileContent: T | null = this.getFileContent(
|
||||
fileId,
|
||||
latestFileContentId,
|
||||
reference,
|
||||
);
|
||||
return fileContent;
|
||||
const fileContent: T | null = this.getFileContent(
|
||||
fileId,
|
||||
latestFileContentId,
|
||||
reference,
|
||||
);
|
||||
return fileContent;
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(
|
||||
storageModel: StorageModel,
|
||||
settingsModel: SettingsModel,
|
||||
chatModel: ChatModel,
|
||||
storageModel: StorageModel,
|
||||
settingsModel: SettingsModel,
|
||||
chatModel: ChatModel,
|
||||
) {
|
||||
this.chatModel = chatModel;
|
||||
this.settingsModel = settingsModel;
|
||||
this.storageModel = storageModel;
|
||||
this.chatModel = chatModel;
|
||||
this.settingsModel = settingsModel;
|
||||
this.storageModel = storageModel;
|
||||
|
||||
this.boardsAndTasksModel = new BoardsAndTasksModel(
|
||||
this.storageModel,
|
||||
this.settingsModel,
|
||||
chatModel,
|
||||
this,
|
||||
);
|
||||
this.boardsAndTasksModel = new BoardsAndTasksModel(
|
||||
this.storageModel,
|
||||
this.settingsModel,
|
||||
chatModel,
|
||||
this,
|
||||
);
|
||||
}
|
||||
|
||||
// utility
|
||||
static generateFileContentId = (creationDate: string): string => {
|
||||
return creationDate + v4();
|
||||
return creationDate + v4();
|
||||
};
|
||||
|
||||
static createFileContent = <T extends string>(
|
||||
fileId: string,
|
||||
type: T,
|
||||
fileId: string,
|
||||
type: T,
|
||||
): FileContent<T> => {
|
||||
const creationDate: string = createTimestamp();
|
||||
const fileContentId: string =
|
||||
FileModel.generateFileContentId(creationDate);
|
||||
const creationDate: string = createTimestamp();
|
||||
const fileContentId: string =
|
||||
FileModel.generateFileContentId(creationDate);
|
||||
|
||||
return {
|
||||
dataVersion: DATA_VERSION,
|
||||
return {
|
||||
dataVersion: DATA_VERSION,
|
||||
|
||||
fileId,
|
||||
fileContentId,
|
||||
creationDate,
|
||||
type,
|
||||
};
|
||||
fileId,
|
||||
fileContentId,
|
||||
creationDate,
|
||||
type,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// paths
|
||||
export enum FileModelSubPath {
|
||||
Data = "data",
|
||||
Model = "model",
|
||||
ModelView = "view",
|
||||
ModelTask = "tasks",
|
||||
ModelCalendar = "calendar",
|
||||
Model = "model",
|
||||
ModelView = "view",
|
||||
ModelTask = "tasks",
|
||||
ModelCalendar = "calendar",
|
||||
}
|
||||
|
||||
// types
|
||||
export interface FileContent<T extends string>
|
||||
extends ValidObject, StringEntryObject {
|
||||
readonly fileId: string;
|
||||
readonly fileContentId: string;
|
||||
readonly creationDate: string;
|
||||
readonly fileId: string;
|
||||
readonly fileContentId: string;
|
||||
readonly creationDate: string;
|
||||
|
||||
readonly type: T;
|
||||
}
|
||||
readonly type: T;
|
||||
}
|
||||
|
||||
// references
|
||||
export const FileContentReference: FileContent<string> = {
|
||||
|
||||
@@ -37,7 +37,7 @@ export default class FileTransferModel {
|
||||
};
|
||||
|
||||
readonly prepareToSend = (): void => {
|
||||
if (!this.transferData) return;
|
||||
if (!this.transferData) return;
|
||||
this.direction = TransferDirections.Send;
|
||||
this.connectionModel.addChannel(this.transferData.channel);
|
||||
};
|
||||
@@ -157,8 +157,7 @@ export default class FileTransferModel {
|
||||
};
|
||||
|
||||
readonly prepareFileForSending = (filePath: string[]): string => {
|
||||
const fileContent: string | null =
|
||||
this.storageModel.read(filePath);
|
||||
const fileContent: string | null = this.storageModel.read(filePath);
|
||||
if (fileContent == null) return "";
|
||||
|
||||
const fileData: FileData = {
|
||||
@@ -169,7 +168,7 @@ export default class FileTransferModel {
|
||||
};
|
||||
|
||||
readonly sendFile = async (stringifiedFileData: string): Promise<void> => {
|
||||
if (!this.transferData) return;
|
||||
if (!this.transferData) return;
|
||||
|
||||
const encryptedFileData: string = await encryptString(
|
||||
stringifiedFileData,
|
||||
|
||||
@@ -46,7 +46,7 @@ export default class SettingsModel {
|
||||
// load
|
||||
private readonly readSetting = (
|
||||
pathName: keyof typeof filePaths.settingsModel,
|
||||
): string|null=> {
|
||||
): string | null => {
|
||||
const path = StorageModel.getPath(
|
||||
StorageModelSubPaths.SettingsModel,
|
||||
filePaths.settingsModel[pathName],
|
||||
|
||||
Binary file not shown.
+171
-149
@@ -1,5 +1,5 @@
|
||||
import { checkIsValidObject, checkMatchesObjectStructure } from "./typeSafety";
|
||||
import * as Hammer from "hammerjs";
|
||||
import * as React from "../../react";
|
||||
|
||||
export interface Stringifiable {
|
||||
toString(): string;
|
||||
@@ -18,7 +18,7 @@ export function createTimestamp(): string {
|
||||
return new Date().toISOString();
|
||||
}
|
||||
|
||||
// filters etc
|
||||
// filters
|
||||
export type StringEntryObject = { [key: string]: Stringifiable | undefined };
|
||||
|
||||
export function filterObjectsByStringEntries<T>(
|
||||
@@ -28,7 +28,7 @@ export function filterObjectsByStringEntries<T>(
|
||||
): Set<T> {
|
||||
const matches: Set<T> = new Set();
|
||||
|
||||
object_loop: for (const object of objects) {
|
||||
for (const object of objects) {
|
||||
const doesMatch: boolean = checkDoesObjectMatchReference(
|
||||
reference,
|
||||
converter(object),
|
||||
@@ -39,79 +39,6 @@ export function filterObjectsByStringEntries<T>(
|
||||
return matches;
|
||||
}
|
||||
|
||||
export function checkDoesObjectMatchReference(
|
||||
reference: StringEntryObject,
|
||||
stringEntryObject: StringEntryObject,
|
||||
explicitEmptyValue: boolean = false,
|
||||
): boolean {
|
||||
reference_entry_loop: for (const referenceEntry of Object.entries(
|
||||
reference,
|
||||
)) {
|
||||
const [referenceKey, referenceValue] = referenceEntry;
|
||||
const stringEntryObjectValue: Stringifiable | undefined =
|
||||
stringEntryObject[referenceKey];
|
||||
|
||||
if (referenceValue == undefined) return false;
|
||||
|
||||
if (referenceValue[0] == "-") {
|
||||
const strippedReferenceValue: string = referenceValue
|
||||
.toString()
|
||||
.substring(1);
|
||||
// property may not exist
|
||||
if (
|
||||
strippedReferenceValue == "" &&
|
||||
stringEntryObjectValue != undefined &&
|
||||
stringEntryObjectValue != ""
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// property may not match
|
||||
if (stringEntryObjectValue == strippedReferenceValue) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (explicitEmptyValue == false) {
|
||||
// property must exist but be anything
|
||||
if (
|
||||
referenceValue == "" &&
|
||||
(stringEntryObjectValue == undefined ||
|
||||
stringEntryObjectValue == "")
|
||||
) {
|
||||
return false;
|
||||
} else if (referenceValue == "") {
|
||||
continue reference_entry_loop;
|
||||
}
|
||||
}
|
||||
|
||||
// property must match
|
||||
if (stringEntryObjectValue != referenceValue) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function collectObjectValuesForKey<T>(
|
||||
key: string,
|
||||
converter: (object: T) => StringEntryObject,
|
||||
objects: T[],
|
||||
): string[] {
|
||||
const values: Set<string> = new Set();
|
||||
|
||||
for (const object of objects) {
|
||||
const stringEntryObject: StringEntryObject = converter(object);
|
||||
const stringEntryObjectValue: Stringifiable | undefined =
|
||||
stringEntryObject[key];
|
||||
if (stringEntryObjectValue == undefined) continue;
|
||||
|
||||
values.add(stringEntryObjectValue.toString());
|
||||
}
|
||||
|
||||
return [...values.values()];
|
||||
}
|
||||
|
||||
export function filterObjectsByWords<T>(
|
||||
query: string,
|
||||
getStringsOfObject: (object: T) => string[],
|
||||
@@ -119,7 +46,7 @@ export function filterObjectsByWords<T>(
|
||||
): Set<T> {
|
||||
const matches: Set<T> = new Set();
|
||||
|
||||
object_loop: for (const object of objects) {
|
||||
for (const object of objects) {
|
||||
const doesMatch: boolean = checkDoesObjectMatchSearch(
|
||||
query,
|
||||
getStringsOfObject,
|
||||
@@ -170,6 +97,26 @@ export function checkDoesObjectMatchSearch<T>(
|
||||
return true;
|
||||
}
|
||||
|
||||
export default function implementFilter<T>(
|
||||
allItems: React.ListState<T>|React.MapState<T>,
|
||||
matches: React.ListState<T>,
|
||||
query: React.State<string>,
|
||||
itemToString: (item: T) => string,
|
||||
) {
|
||||
function update() {
|
||||
matches.clear();
|
||||
allItems.value.forEach((item: T) => {
|
||||
if (!itemToString(item).includes(query.value)) return;
|
||||
matches.add(item);
|
||||
allItems.handleRemoval(item, () => {
|
||||
matches.remove(item);
|
||||
});
|
||||
});
|
||||
}
|
||||
query.subscribe(update);
|
||||
allItems.handleAddition(update);
|
||||
}
|
||||
|
||||
// handlers
|
||||
export type Handler<T> = (item: T) => void;
|
||||
|
||||
@@ -313,99 +260,174 @@ export function implementPinchZoom(canvas: HTMLElement) {
|
||||
const MIN = 0.25;
|
||||
const MAX = 5;
|
||||
|
||||
const element = (): HTMLElement|null=> canvas.querySelector(".zoom");
|
||||
const element = (): HTMLElement | null => canvas.querySelector(".zoom");
|
||||
const distance = (e: TouchEvent) =>
|
||||
Math.hypot(
|
||||
e.touches[0].pageX - e.touches[1].pageX,
|
||||
e.touches[0].pageY - e.touches[1].pageY,
|
||||
);
|
||||
Math.hypot(
|
||||
e.touches[0].pageX - e.touches[1].pageX,
|
||||
e.touches[0].pageY - e.touches[1].pageY,
|
||||
);
|
||||
const point = (e: TouchEvent, direction: "x" | "y", i: number) =>
|
||||
e.touches[i][direction == "x" ? "clientX" : "clientY"];
|
||||
e.touches[i][direction == "x" ? "clientX" : "clientY"];
|
||||
const midpoint = (e: TouchEvent, direction: "x" | "y") =>
|
||||
(point(e, direction, 0) + point(e, direction, 1)) / 2;
|
||||
(point(e, direction, 0) + point(e, direction, 1)) / 2;
|
||||
|
||||
function apply(factor: number, _offset?: [number, number]) {
|
||||
const el = element();
|
||||
if (!el) return;
|
||||
if (factor < MIN) return apply(MIN, _offset);
|
||||
if (factor > MAX) return apply(5, _offset);
|
||||
const el = element();
|
||||
if (!el) return;
|
||||
if (factor < MIN) return apply(MIN, _offset);
|
||||
if (factor > MAX) return apply(5, _offset);
|
||||
|
||||
let x: number, y: number;
|
||||
if (_offset) [x, y] = _offset;
|
||||
else {
|
||||
x = currentX
|
||||
y = currentY
|
||||
}
|
||||
el.style.transform = `scale(${factor.toString()}) translate(${x}px, ${y}px)`;
|
||||
currentX = x;
|
||||
currentY = y;
|
||||
currentZoom = factor;
|
||||
let x: number, y: number;
|
||||
if (_offset) [x, y] = _offset;
|
||||
else {
|
||||
x = currentX;
|
||||
y = currentY;
|
||||
}
|
||||
el.style.transform = `scale(${factor.toString()}) translate(${x}px, ${y}px)`;
|
||||
currentX = x;
|
||||
currentY = y;
|
||||
currentZoom = factor;
|
||||
}
|
||||
|
||||
canvas.addEventListener("wheel", (event: WheelEvent) => {
|
||||
event.preventDefault();
|
||||
event.preventDefault();
|
||||
|
||||
initialZoom = currentZoom;
|
||||
initialX = currentX;
|
||||
initialY = currentY;
|
||||
initialZoom = currentZoom;
|
||||
initialX = currentX;
|
||||
initialY = currentY;
|
||||
|
||||
if (!event.shiftKey) {
|
||||
apply(currentZoom, [
|
||||
currentX - event.deltaX,
|
||||
currentY - event.deltaY,
|
||||
]);
|
||||
return;
|
||||
}
|
||||
apply(currentZoom - event.deltaY * 0.01);
|
||||
if (!event.shiftKey) {
|
||||
apply(currentZoom, [
|
||||
currentX - event.deltaX,
|
||||
currentY - event.deltaY,
|
||||
]);
|
||||
return;
|
||||
}
|
||||
apply(currentZoom - event.deltaY * 0.01);
|
||||
});
|
||||
canvas.addEventListener("scroll", (event: Event) => {
|
||||
event.preventDefault();
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
canvas.addEventListener("touchstart", (event: TouchEvent) => {
|
||||
(document.activeElement as HTMLElement).blur();
|
||||
(document.activeElement as HTMLElement).blur();
|
||||
|
||||
const el = element();
|
||||
if (!el) return;
|
||||
if (lastElement != undefined && lastElement != el) reset();
|
||||
lastElement = el;
|
||||
const el = element();
|
||||
if (!el) return;
|
||||
if (lastElement != undefined && lastElement != el) reset();
|
||||
lastElement = el;
|
||||
|
||||
initialZoom = currentZoom;
|
||||
initialX = currentX;
|
||||
initialY = currentY;
|
||||
initialZoom = currentZoom;
|
||||
initialX = currentX;
|
||||
initialY = currentY;
|
||||
|
||||
if (event.touches.length != 2) {
|
||||
pinching = false;
|
||||
initialTouchX = event.touches[0].clientX;
|
||||
initialTouchY = event.touches[0].clientY;
|
||||
return;
|
||||
}
|
||||
if (event.touches.length != 2) {
|
||||
pinching = false;
|
||||
initialTouchX = event.touches[0].clientX;
|
||||
initialTouchY = event.touches[0].clientY;
|
||||
return;
|
||||
}
|
||||
|
||||
pinching = true;
|
||||
initialDistance = distance(event);
|
||||
initialTouchX = midpoint(event, "x");
|
||||
initialTouchY = midpoint(event, "y");
|
||||
pinching = true;
|
||||
initialDistance = distance(event);
|
||||
initialTouchX = midpoint(event, "x");
|
||||
initialTouchY = midpoint(event, "y");
|
||||
});
|
||||
canvas.addEventListener("touchmove", (event: TouchEvent) => {
|
||||
if (!pinching) {
|
||||
apply(currentZoom, [
|
||||
initialX +
|
||||
(event.touches[0].clientX - initialTouchX) / initialZoom,
|
||||
initialY +
|
||||
(event.touches[0].clientY - initialTouchY) / initialZoom,
|
||||
]);
|
||||
return;
|
||||
}
|
||||
if (event.touches.length < 2) return;
|
||||
event.preventDefault();
|
||||
const currentDistance = distance(event);
|
||||
const midX = midpoint(event, "x");
|
||||
const midY = midpoint(event, "y");
|
||||
const ratio = currentDistance / initialDistance;
|
||||
const difference = currentDistance - initialDistance;
|
||||
apply(initialZoom * ratio, [
|
||||
initialX + (midX - difference - initialTouchX) / initialZoom,
|
||||
initialY + (midY - difference - initialTouchY) / initialZoom,
|
||||
]);
|
||||
if (!pinching) {
|
||||
apply(currentZoom, [
|
||||
initialX +
|
||||
(event.touches[0].clientX - initialTouchX) / initialZoom,
|
||||
initialY +
|
||||
(event.touches[0].clientY - initialTouchY) / initialZoom,
|
||||
]);
|
||||
return;
|
||||
}
|
||||
if (event.touches.length < 2) return;
|
||||
event.preventDefault();
|
||||
const currentDistance = distance(event);
|
||||
const midX = midpoint(event, "x");
|
||||
const midY = midpoint(event, "y");
|
||||
const ratio = currentDistance / initialDistance;
|
||||
const difference = currentDistance - initialDistance;
|
||||
apply(initialZoom * ratio, [
|
||||
initialX + (midX - difference - initialTouchX) / initialZoom,
|
||||
initialY + (midY - difference - initialTouchY) / initialZoom,
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
// objecs
|
||||
export function collectObjectValuesForKey<T>(
|
||||
key: string,
|
||||
converter: (object: T) => StringEntryObject,
|
||||
objects: T[],
|
||||
): string[] {
|
||||
const values: Set<string> = new Set();
|
||||
|
||||
for (const object of objects) {
|
||||
const stringEntryObject: StringEntryObject = converter(object);
|
||||
const stringEntryObjectValue: Stringifiable | undefined =
|
||||
stringEntryObject[key];
|
||||
if (stringEntryObjectValue == undefined) continue;
|
||||
|
||||
values.add(stringEntryObjectValue.toString());
|
||||
}
|
||||
|
||||
return [...values.values()];
|
||||
}
|
||||
|
||||
// type safety
|
||||
export function checkDoesObjectMatchReference(
|
||||
reference: StringEntryObject,
|
||||
stringEntryObject: StringEntryObject,
|
||||
explicitEmptyValue: boolean = false,
|
||||
): boolean {
|
||||
reference_entry_loop: for (const referenceEntry of Object.entries(
|
||||
reference,
|
||||
)) {
|
||||
const [referenceKey, referenceValue] = referenceEntry;
|
||||
const stringEntryObjectValue: Stringifiable | undefined =
|
||||
stringEntryObject[referenceKey];
|
||||
|
||||
if (referenceValue == undefined) return false;
|
||||
|
||||
if (referenceValue[0] == "-") {
|
||||
const strippedReferenceValue: string = referenceValue
|
||||
.toString()
|
||||
.substring(1);
|
||||
// property may not exist
|
||||
if (
|
||||
strippedReferenceValue == "" &&
|
||||
stringEntryObjectValue != undefined &&
|
||||
stringEntryObjectValue != ""
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// property may not match
|
||||
if (stringEntryObjectValue == strippedReferenceValue) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (explicitEmptyValue == false) {
|
||||
// property must exist but be anything
|
||||
if (
|
||||
referenceValue == "" &&
|
||||
(stringEntryObjectValue == undefined ||
|
||||
stringEntryObjectValue == "")
|
||||
) {
|
||||
return false;
|
||||
} else if (referenceValue == "") {
|
||||
continue reference_entry_loop;
|
||||
}
|
||||
}
|
||||
|
||||
// property must match
|
||||
if (stringEntryObjectValue != referenceValue) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user