Compare commits

...

9 Commits
3.3.0 ... 3.3.2

Author SHA1 Message Date
Athou
6de817f539 release 3.3.2 2023-05-20 14:00:54 +02:00
Athou
08a2746921 restore entry selection indicator 2023-05-19 10:37:59 +02:00
Athou
bc28727e39 remove warnings 2023-05-17 16:14:21 +02:00
Athou
eceaf3a98d remove lodash to reduce bundle size by 100kb 2023-05-17 16:11:32 +02:00
Athou
4a8939e5e5 optimized png sizes 2023-05-17 15:47:22 +02:00
Athou
e90b80c641 send GA pageviews only if initialized 2023-05-17 13:43:25 +02:00
Athou
2979600cc2 add dividers to separate read-only information from forms 2023-05-11 11:45:23 +02:00
Athou
a2deef7f7f release 3.3.1 2023-05-10 20:26:45 +02:00
Athou
b5097d4fc3 fix long feed names not being shortened to respect tree max width (#1055) 2023-05-10 20:25:50 +02:00
21 changed files with 12105 additions and 12073 deletions

View File

@@ -1,12 +1,21 @@
# Changelog # Changelog
## [3.3.2]
- restore entry selection indicator (left orange border) that was lost with the mantine 6.x upgrade (3.3.0)
- add dividers to visually separate read-only information from forms on feed and category details pages
- reduced js bundle size by 10%
## [3.3.1]
- fix long feed names not being shortened to respect tree max width
## [3.3.0] ## [3.3.0]
- there are now database changes, rolling back to 2.x will no longer be possible - there are now database changes, rolling back to 2.x will no longer be possible
- restore support for user custom CSS rules - restore support for user custom CSS rules
- add support for user custom JS code that will be executed on page load - add support for user custom JS code that will be executed on page load
## [3.2.0] ## [3.2.0]
- restore the welcome page - restore the welcome page
@@ -28,10 +37,10 @@
## [3.0.1] ## [3.0.1]
- allow env variable substitution in config.yml - allow env variable substitution in config.yml
- e.g. having a custom config.yml file with `app.session.path=${SOME_ENV_VAR}` will substitute `SOME_ENV_VAR` with - e.g. having a custom config.yml file with `app.session.path=${SOME_ENV_VAR}` will substitute `SOME_ENV_VAR` with
its value its value
- allow env variable prefixed with `CF_` to override config.yml properties - allow env variable prefixed with `CF_` to override config.yml properties
- e.g. setting `CF_APP_ALLOWREGISTRATIONS=true` will set `app.allowRegistrations` to `true` - e.g. setting `CF_APP_ALLOWREGISTRATIONS=true` will set `app.allowRegistrations` to `true`
## [3.0.0] ## [3.0.0]
@@ -138,4 +147,4 @@
consumption and better overall performances. consumption and better overall performances.
See the README on how to build CommaFeed from now on. See the README on how to build CommaFeed from now on.
- CommaFeed should no longer fetch the same feed multiple times in a row - CommaFeed should no longer fetch the same feed multiple times in a row
- Users can use their username or email to log in - Users can use their username or email to log in

File diff suppressed because it is too large Load Diff

View File

@@ -1,84 +1,84 @@
{ {
"name": "commafeed-client", "name": "commafeed-client",
"private": true, "private": true,
"version": "0.0.0", "version": "0.0.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite --host", "dev": "vite --host",
"dev:typescript": "tsc --watch", "dev:typescript": "tsc --watch",
"build": "npm run i18n:compile && tsc && vite build", "build": "npm run i18n:compile && tsc && vite build",
"preview": "vite preview", "preview": "vite preview",
"test": "vitest", "test": "vitest",
"test:ci": "vitest run", "test:ci": "vitest run",
"eslint": "eslint --ext=.js,.jsx,.ts,.tsx src", "eslint": "eslint --ext=.js,.jsx,.ts,.tsx src",
"i18n": "npm run i18n:extract && npm run i18n:compile", "i18n": "npm run i18n:extract && npm run i18n:compile",
"i18n:extract": "lingui extract --clean", "i18n:extract": "lingui extract --clean",
"i18n:compile": "lingui compile --typescript", "i18n:compile": "lingui compile --typescript",
"postinstall": "npm run i18n:compile" "postinstall": "npm run i18n:compile"
}, },
"dependencies": { "dependencies": {
"@emotion/react": "^11.11.0", "@emotion/react": "^11.11.0",
"@fontsource/open-sans": "^4.5.14", "@fontsource/open-sans": "^4.5.14",
"@lingui/core": "^4.0.0", "@lingui/core": "^4.0.0",
"@lingui/macro": "^4.0.0", "@lingui/macro": "^4.0.0",
"@lingui/react": "^4.0.0", "@lingui/react": "^4.0.0",
"@mantine/core": "^6.0.10", "@mantine/core": "^6.0.10",
"@mantine/form": "^6.0.10", "@mantine/form": "^6.0.10",
"@mantine/hooks": "^6.0.10", "@mantine/hooks": "^6.0.10",
"@mantine/modals": "^6.0.10", "@mantine/modals": "^6.0.10",
"@mantine/notifications": "^6.0.10", "@mantine/notifications": "^6.0.10",
"@mantine/spotlight": "^6.0.10", "@mantine/spotlight": "^6.0.10",
"@mantine/styles": "^6.0.10", "@mantine/styles": "^6.0.10",
"@reduxjs/toolkit": "^1.9.5", "@reduxjs/toolkit": "^1.9.5",
"axios": "^1.4.0", "axios": "^1.4.0",
"dayjs": "^1.11.7", "dayjs": "^1.11.7",
"interweave": "^13.1.0", "interweave": "^13.1.0",
"lodash": "^4.17.21", "mousetrap": "^1.6.5",
"mousetrap": "^1.6.5", "react": "^18.2.0",
"react": "^18.2.0", "react-async-hook": "^4.0.0",
"react-async-hook": "^4.0.0", "react-contexify": "^6.0.0",
"react-contexify": "^6.0.0", "react-dom": "^18.2.0",
"react-dom": "^18.2.0", "react-ga4": "^2.1.0",
"react-ga4": "^2.1.0", "react-icons": "^4.8.0",
"react-icons": "^4.8.0", "react-infinite-scroller": "^1.2.6",
"react-infinite-scroller": "^1.2.6", "react-redux": "^8.0.5",
"react-redux": "^8.0.5", "react-router-dom": "^6.11.1",
"react-router-dom": "^6.11.1", "react-swipeable": "^7.0.0",
"react-swipeable": "^7.0.0", "swagger-ui-react": "^4.18.3",
"swagger-ui-react": "^4.18.3", "throttle-debounce": "^5.0.0",
"tinycon": "^0.6.8", "tinycon": "^0.6.8",
"use-local-storage": "^3.0.0", "use-local-storage": "^3.0.0",
"websocket-heartbeat-js": "^1.1.2" "websocket-heartbeat-js": "^1.1.2"
}, },
"devDependencies": { "devDependencies": {
"@lingui/cli": "^4.0.0", "@lingui/cli": "^4.0.0",
"@lingui/vite-plugin": "^4.0.0", "@lingui/vite-plugin": "^4.0.0",
"@types/eslint": "^8.37.0", "@types/eslint": "^8.37.0",
"@types/lodash": "^4.14.194", "@types/mousetrap": "^1.6.11",
"@types/mousetrap": "^1.6.11", "@types/react": "^18.2.6",
"@types/react": "^18.2.6", "@types/react-dom": "^18.2.4",
"@types/react-dom": "^18.2.4", "@types/react-infinite-scroller": "^1.2.3",
"@types/react-infinite-scroller": "^1.2.3", "@types/swagger-ui-react": "^4.18.0",
"@types/swagger-ui-react": "^4.18.0", "@types/throttle-debounce": "^5.0.0",
"@types/tinycon": "^0.6.3", "@types/tinycon": "^0.6.3",
"@typescript-eslint/eslint-plugin": "^5.59.2", "@typescript-eslint/eslint-plugin": "^5.59.2",
"@typescript-eslint/parser": "^5.59.2", "@typescript-eslint/parser": "^5.59.2",
"@vitejs/plugin-react": "^4.0.0", "@vitejs/plugin-react": "^4.0.0",
"babel-plugin-macros": "^3.1.0", "babel-plugin-macros": "^3.1.0",
"eslint": "^8.40.0", "eslint": "^8.40.0",
"eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^17.0.0", "eslint-config-airbnb-typescript": "^17.0.0",
"eslint-config-prettier": "^8.8.0", "eslint-config-prettier": "^8.8.0",
"eslint-config-react-app": "^7.0.1", "eslint-config-react-app": "^7.0.1",
"eslint-plugin-hooks": "^0.4.3", "eslint-plugin-hooks": "^0.4.3",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^4.2.1",
"prettier": "^2.8.8", "prettier": "^2.8.8",
"rollup-plugin-visualizer": "^5.9.0", "rollup-plugin-visualizer": "^5.9.0",
"typescript": "^5.0.4", "typescript": "^5.0.4",
"vite": "^4.3.5", "vite": "^4.3.5",
"vite-plugin-eslint": "^1.8.1", "vite-plugin-eslint": "^1.8.1",
"vite-tsconfig-paths": "^4.2.0", "vite-tsconfig-paths": "^4.2.0",
"vitest": "^0.31.0", "vitest": "^0.31.0",
"vitest-mock-extended": "^1.1.3" "vitest-mock-extended": "^1.1.3"
} }
} }

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.commafeed</groupId> <groupId>com.commafeed</groupId>
<artifactId>commafeed</artifactId> <artifactId>commafeed</artifactId>
<version>3.3.0</version> <version>3.3.2</version>
</parent> </parent>
<artifactId>commafeed-client</artifactId> <artifactId>commafeed-client</artifactId>
<name>CommaFeed Client</name> <name>CommaFeed Client</name>

View File

@@ -122,7 +122,7 @@ function GoogleAnalyticsHandler() {
}, [googleAnalyticsCode]) }, [googleAnalyticsCode])
useEffect(() => { useEffect(() => {
ReactGA.send({ hitType: "pageview", page: location.pathname }) if (ReactGA.isInitialized) ReactGA.send({ hitType: "pageview", page: location.pathname })
}, [location]) }, [location])
return null return null

View File

@@ -64,3 +64,5 @@ export const openLinkInBackgroundTab = (url: string) => {
}) })
) )
} }
export const truncate = (str: string, n: number) => (str.length > n ? `${str.slice(0, n - 1)}\u2026` : str)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 44 KiB

View File

@@ -18,9 +18,9 @@ import { KeyboardShortcutsHelp } from "components/KeyboardShortcutsHelp"
import { Loader } from "components/Loader" import { Loader } from "components/Loader"
import { useMousetrap } from "hooks/useMousetrap" import { useMousetrap } from "hooks/useMousetrap"
import { useViewMode } from "hooks/useViewMode" import { useViewMode } from "hooks/useViewMode"
import throttle from "lodash/throttle"
import { useEffect } from "react" import { useEffect } from "react"
import InfiniteScroll from "react-infinite-scroller" import InfiniteScroll from "react-infinite-scroller"
import { throttle } from "throttle-debounce"
import { FeedEntry } from "./FeedEntry" import { FeedEntry } from "./FeedEntry"
export function FeedEntries() { export function FeedEntries() {
@@ -82,7 +82,7 @@ export function FeedEntries() {
) )
} }
} }
const throttledListener = throttle(listener, 100) const throttledListener = throttle(100, listener)
scrollArea?.addEventListener("scroll", throttledListener) scrollArea?.addEventListener("scroll", throttledListener)
return () => scrollArea?.removeEventListener("scroll", throttledListener) return () => scrollArea?.removeEventListener("scroll", throttledListener)
}, [dispatch, entries, viewMode, scrollMarks, scrollingToEntry]) }, [dispatch, entries, viewMode, scrollMarks, scrollingToEntry])

View File

@@ -63,7 +63,8 @@ const useStyles = createStyles((theme, props: FeedEntryProps & { viewMode?: View
} }
if (props.showSelectionIndicator) { if (props.showSelectionIndicator) {
styles.paper.borderLeftColor = theme.colorScheme === "dark" ? theme.colors.orange[4] : theme.colors.orange[6] const borderLeftColor = theme.colorScheme === "dark" ? theme.colors.orange[4] : theme.colors.orange[6]
styles.paper.borderLeftColor = `${borderLeftColor} !important`
} }
return styles return styles

View File

@@ -5,11 +5,11 @@ import { markEntriesUpToEntry, markEntry, starEntry } from "app/slices/entries"
import { redirectToFeed } from "app/slices/redirect" import { redirectToFeed } from "app/slices/redirect"
import { useAppDispatch, useAppSelector } from "app/store" import { useAppDispatch, useAppSelector } from "app/store"
import { Entry } from "app/types" import { Entry } from "app/types"
import { openLinkInBackgroundTab } from "app/utils" import { openLinkInBackgroundTab, truncate } from "app/utils"
import { throttle, truncate } from "lodash"
import { useEffect } from "react" import { useEffect } from "react"
import { Item, Menu, Separator, useContextMenu } from "react-contexify" import { Item, Menu, Separator, useContextMenu } from "react-contexify"
import { TbArrowBarToDown, TbExternalLink, TbEyeCheck, TbEyeOff, TbRss, TbStar, TbStarOff } from "react-icons/tb" import { TbArrowBarToDown, TbExternalLink, TbEyeCheck, TbEyeOff, TbRss, TbStar, TbStarOff } from "react-icons/tb"
import { throttle } from "throttle-debounce"
interface FeedEntryContextMenuProps { interface FeedEntryContextMenuProps {
entry: Entry entry: Entry
@@ -92,7 +92,7 @@ export function FeedEntryContextMenu(props: FeedEntryContextMenuProps) {
> >
<Group> <Group>
<TbRss size={iconSize} /> <TbRss size={iconSize} />
<Trans>Go to {truncate(props.entry.feedName)}</Trans> <Trans>Go to {truncate(props.entry.feedName, 30)}</Trans>
</Group> </Group>
</Item> </Item>
</> </>
@@ -118,7 +118,7 @@ export function useFeedEntryContextMenu(entry: Entry) {
const scrollArea = document.getElementById(Constants.dom.mainScrollAreaId) const scrollArea = document.getElementById(Constants.dom.mainScrollAreaId)
const listener = () => contextMenu.hideAll() const listener = () => contextMenu.hideAll()
const throttledListener = throttle(listener, 100) const throttledListener = throttle(100, listener)
scrollArea?.addEventListener("scroll", throttledListener) scrollArea?.addEventListener("scroll", throttledListener)
return () => scrollArea?.removeEventListener("scroll", throttledListener) return () => scrollArea?.removeEventListener("scroll", throttledListener)

View File

@@ -7,9 +7,9 @@ import { useAppDispatch, useAppSelector } from "app/store"
import { Entry } from "app/types" import { Entry } from "app/types"
import { ActionButton } from "components/ActionButtton" import { ActionButton } from "components/ActionButtton"
import { ButtonToolbar } from "components/ButtonToolbar" import { ButtonToolbar } from "components/ButtonToolbar"
import { throttle } from "lodash"
import { useEffect, useState } from "react" import { useEffect, useState } from "react"
import { TbArrowBarToDown, TbExternalLink, TbEyeCheck, TbEyeOff, TbShare, TbStar, TbStarOff, TbTag } from "react-icons/tb" import { TbArrowBarToDown, TbExternalLink, TbEyeCheck, TbEyeOff, TbShare, TbStar, TbStarOff, TbTag } from "react-icons/tb"
import { throttle } from "throttle-debounce"
import { ShareButtons } from "./ShareButtons" import { ShareButtons } from "./ShareButtons"
interface FeedEntryFooterProps { interface FeedEntryFooterProps {
@@ -38,7 +38,7 @@ export function FeedEntryFooter(props: FeedEntryFooterProps) {
const scrollArea = document.getElementById(Constants.dom.mainScrollAreaId) const scrollArea = document.getElementById(Constants.dom.mainScrollAreaId)
const listener = () => setScrollPosition(scrollArea ? scrollArea.scrollTop : 0) const listener = () => setScrollPosition(scrollArea ? scrollArea.scrollTop : 0)
const throttledListener = throttle(listener, 100) const throttledListener = throttle(100, listener)
scrollArea?.addEventListener("scroll", throttledListener) scrollArea?.addEventListener("scroll", throttledListener)
return () => scrollArea?.removeEventListener("scroll", throttledListener) return () => scrollArea?.removeEventListener("scroll", throttledListener)

View File

@@ -108,6 +108,8 @@ export function CategoryDetailsPage() {
{editable && ( {editable && (
<> <>
<Divider />
<TextInput label={<Trans>Name</Trans>} {...form.getInputProps("name")} required /> <TextInput label={<Trans>Name</Trans>} {...form.getInputProps("name")} required />
<CategorySelect <CategorySelect
label={<Trans>Parent Category</Trans>} label={<Trans>Parent Category</Trans>}

View File

@@ -151,6 +151,8 @@ export function FeedDetailsPage() {
</Box> </Box>
</Input.Wrapper> </Input.Wrapper>
<Divider />
<TextInput label={<Trans>Name</Trans>} {...form.getInputProps("name")} required /> <TextInput label={<Trans>Name</Trans>} {...form.getInputProps("name")} required />
<CategorySelect label={<Trans>Category</Trans>} {...form.getInputProps("categoryId")} clearable /> <CategorySelect label={<Trans>Category</Trans>} {...form.getInputProps("categoryId")} clearable />
<NumberInput label={<Trans>Position</Trans>} {...form.getInputProps("position")} required min={0} /> <NumberInput label={<Trans>Position</Trans>} {...form.getInputProps("position")} required min={0} />

View File

@@ -40,7 +40,7 @@ const sidebarRightBorderWidth = "1px"
const useStyles = createStyles(theme => ({ const useStyles = createStyles(theme => ({
sidebarContent: { sidebarContent: {
maxWidth: `calc(${Constants.layout.sidebarWidth} - ${sidebarPadding} * 2 - ${sidebarRightBorderWidth})`, maxWidth: `calc(${Constants.layout.sidebarWidth}px - ${sidebarPadding} * 2 - ${sidebarRightBorderWidth})`,
[theme.fn.smallerThan(Constants.layout.mobileBreakpoint)]: { [theme.fn.smallerThan(Constants.layout.mobileBreakpoint)]: {
maxWidth: `calc(100vw - ${sidebarPadding} * 2 - ${sidebarRightBorderWidth})`, maxWidth: `calc(100vw - ${sidebarPadding} * 2 - ${sidebarRightBorderWidth})`,
}, },

View File

@@ -6,15 +6,12 @@
<parent> <parent>
<groupId>com.commafeed</groupId> <groupId>com.commafeed</groupId>
<artifactId>commafeed</artifactId> <artifactId>commafeed</artifactId>
<version>3.3.0</version> <version>3.3.2</version>
</parent> </parent>
<artifactId>commafeed-server</artifactId> <artifactId>commafeed-server</artifactId>
<name>CommaFeed Server</name> <name>CommaFeed Server</name>
<properties> <properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<guice.version>5.1.0</guice.version> <guice.version>5.1.0</guice.version>
<querydsl.version>4.4.0</querydsl.version> <querydsl.version>4.4.0</querydsl.version>
<rome.version>2.1.0</rome.version> <rome.version>2.1.0</rome.version>
@@ -42,14 +39,6 @@
</resources> </resources>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<parameters>true</parameters>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
@@ -237,7 +226,7 @@
<dependency> <dependency>
<groupId>com.commafeed</groupId> <groupId>com.commafeed</groupId>
<artifactId>commafeed-client</artifactId> <artifactId>commafeed-client</artifactId>
<version>3.3.0</version> <version>3.3.2</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@@ -3,7 +3,6 @@ package com.commafeed.backend.cache;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.DefaultJedisClientConfig; import redis.clients.jedis.DefaultJedisClientConfig;
import redis.clients.jedis.HostAndPort; import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisClientConfig; import redis.clients.jedis.JedisClientConfig;
@@ -11,7 +10,6 @@ import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig; import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Protocol; import redis.clients.jedis.Protocol;
@Slf4j
@Getter @Getter
public class RedisPoolFactory { public class RedisPoolFactory {

View File

@@ -20,6 +20,8 @@ import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor @RequiredArgsConstructor
abstract class AbstractCustomCodeServlet extends HttpServlet { abstract class AbstractCustomCodeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private final SessionFactory sessionFactory; private final SessionFactory sessionFactory;
private final UserSettingsDAO userSettingsDAO; private final UserSettingsDAO userSettingsDAO;

View File

@@ -9,6 +9,8 @@ import com.commafeed.backend.model.UserSettings;
public class CustomCssServlet extends AbstractCustomCodeServlet { public class CustomCssServlet extends AbstractCustomCodeServlet {
private static final long serialVersionUID = 1L;
@Inject @Inject
public CustomCssServlet(SessionFactory sessionFactory, UserSettingsDAO userSettingsDAO) { public CustomCssServlet(SessionFactory sessionFactory, UserSettingsDAO userSettingsDAO) {
super(sessionFactory, userSettingsDAO); super(sessionFactory, userSettingsDAO);

View File

@@ -11,6 +11,8 @@ import com.commafeed.backend.model.UserSettings;
@Singleton @Singleton
public class CustomJsServlet extends AbstractCustomCodeServlet { public class CustomJsServlet extends AbstractCustomCodeServlet {
private static final long serialVersionUID = 1L;
@Inject @Inject
public CustomJsServlet(SessionFactory sessionFactory, UserSettingsDAO userSettingsDAO) { public CustomJsServlet(SessionFactory sessionFactory, UserSettingsDAO userSettingsDAO) {
super(sessionFactory, userSettingsDAO); super(sessionFactory, userSettingsDAO);

19
pom.xml
View File

@@ -1,18 +1,33 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.commafeed</groupId> <groupId>com.commafeed</groupId>
<artifactId>commafeed</artifactId> <artifactId>commafeed</artifactId>
<version>3.3.0</version> <version>3.3.2</version>
<name>CommaFeed</name> <name>CommaFeed</name>
<packaging>pom</packaging> <packaging>pom</packaging>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties> </properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<parameters>true</parameters>
</configuration>
</plugin>
</plugins>
</build>
<modules> <modules>
<module>commafeed-client</module> <module>commafeed-client</module>
<module>commafeed-server</module> <module>commafeed-server</module>